Bug 1313429 - Implements basic Touch Bar functions. r?spohl,mstange draft
authorHarry Twyford <htwyford@mozilla.com>
Tue, 19 Jun 2018 16:25:42 -0400
changeset 810983 c180ab622df5a9963e4002fba6571dda99e5319c
parent 810379 6e8e861540e6d8c85c73ab7b2afa1f027fb3750c
push id114177
push userbmo:htwyford@mozilla.com
push dateTue, 26 Jun 2018 21:35:24 +0000
reviewersspohl, mstange
bugs1313429
milestone63.0a1
Bug 1313429 - Implements basic Touch Bar functions. r?spohl,mstange MozReview-Commit-ID: 2GSeKcbg6sB
modules/libpref/init/all.js
toolkit/components/telemetry/Scalars.yaml
toolkit/locales/en-US/chrome/global/touchbar.properties
toolkit/locales/jar.mn
widget/cocoa/cursors/back@2x.png
widget/cocoa/cursors/forward@2x.png
widget/cocoa/cursors/fullscreen@2x.png
widget/cocoa/cursors/home@2x.png
widget/cocoa/cursors/readermode@2x.png
widget/cocoa/cursors/refresh@2x.png
widget/cocoa/cursors/search@2x.png
widget/cocoa/cursors/share@2x.png
widget/cocoa/cursors/sidebar@2x.png
widget/cocoa/cursors/star@2x.png
widget/cocoa/cursors/tabnew@2x.png
widget/cocoa/moz.build
widget/cocoa/nsCocoaWindow.h
widget/cocoa/nsCocoaWindow.mm
widget/cocoa/nsTouchBar.h
widget/cocoa/nsTouchBar.mm
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -272,16 +272,21 @@ pref("ui.click_hold_context_menus", fals
 // 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);
 
+#if defined(XP_MACOSX)
+// 0-2 define different Touch Bar layouts
+pref("ui.touchbar.layout", 0);
+#endif
+
 pref("browser.display.use_document_fonts",  1);  // 0 = never, 1 = quick, 2 = always
 // 0 = default: always, except in high contrast mode
 // 1 = always
 // 2 = never
 pref("browser.display.document_color_use", 0);
 pref("browser.display.use_system_colors",   false);
 pref("browser.display.foreground_color",    "#000000");
 pref("browser.display.background_color",    "#FFFFFF");
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -1742,16 +1742,45 @@ memoryreporter:
     expires: "66"
     kind: uint
     notification_emails:
       - memshrink-telemetry-alerts@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - 'content'
 
+# The following section contains Macbook Pro Touch Bar scalars
+touchbar:
+  enabled:
+    bug_numbers:
+      - 1313429
+    description: >
+      If the user has an enabled Touch Bar.
+    expires: "65"
+    kind: boolean
+    notification_emails:
+      - htwyford@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
+  button_pressed:
+    bug_numbers:
+      - 1313429
+    description: >
+      Which buttons are pressed on the Macbook Pro Touch Bar.
+    keyed: true
+    expires: "65"
+    kind: uint
+    notification_emails:
+      - htwyford@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - 'main'
+
 # The following section is for probes testing the Telemetry system. They will not be
 # submitted in pings and are only used for testing.
 telemetry.test:
   unsigned_int_kind:
     bug_numbers:
       - 1276190
     description: >
       This is a test uint type with a really long description, maybe spanning even multiple
new file mode 100644
--- /dev/null
+++ b/toolkit/locales/en-US/chrome/global/touchbar.properties
@@ -0,0 +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/.
+
+
+back = Back
+forward = Forward
+reload = Reload
+fullScreen = Fullscreen
+readerView = Reader View
+find = Find
+newTab = New Tab
+home = Home
+addBookmark = Add Bookmark
+openBookmarksSidebar = Open Bookmarks Sidebar
+tabList = Tab List
+openLocation = Search or enter address
--- a/toolkit/locales/jar.mn
+++ b/toolkit/locales/jar.mn
@@ -37,16 +37,17 @@
   locale/@AB_CD@/global/datetimebox.dtd                 (%chrome/global/datetimebox.dtd)
   locale/@AB_CD@/global/dialogOverlay.dtd               (%chrome/global/dialogOverlay.dtd)
 #ifndef MOZ_FENNEC
   locale/@AB_CD@/global/editMenuOverlay.dtd             (%chrome/global/editMenuOverlay.dtd)
 #endif
   locale/@AB_CD@/global/extensions.properties           (%chrome/global/extensions.properties)
   locale/@AB_CD@/global/fallbackMenubar.properties      (%chrome/global/fallbackMenubar.properties)
   locale/@AB_CD@/global/filepicker.properties           (%chrome/global/filepicker.properties)
+  locale/@AB_CD@/global/touchbar.properties             (%chrome/global/touchbar.properties)
 #ifndef MOZ_FENNEC
   locale/@AB_CD@/global/findbar.dtd                     (%chrome/global/findbar.dtd)
   locale/@AB_CD@/global/findbar.properties              (%chrome/global/findbar.properties)
 #endif
   locale/@AB_CD@/global/globalKeys.dtd                  (%chrome/global/globalKeys.dtd)
   locale/@AB_CD@/global/intl.css                        (%chrome/global/intl.css)
   locale/@AB_CD@/global/intl.properties                 (%chrome/global/intl.properties)
   locale/@AB_CD@/global/keys.properties                 (%chrome/global/keys.properties)
new file mode 100644
index 0000000000000000000000000000000000000000..f24ddb89f78825f07281817547632d9e6cb349b1
GIT binary patch
literal 390
zc$@)-0eSw3P)<h;3K|Lk000e1NJLTq001BW000~a1^@s60K&Z@00001b5ch_0Itp)
z=>Px$KuJVFR7efQm%UEJFbv1*N>SSv;7NFZn-~#K!^8;74Ll11iGk@J1~J@zYD?7k
z>;o#5d>_Th)H=5Rzci_nR8?l{`+hTy`gs_}r^Dg%GBezA2g?#L41>M`z<YA3*$olj
z+qSt0ghabeiK1TQ@LQZ?0P5s;pGHywmpCOfB>(73oNA8(_{0(6PARoZ74rE7*FZ?T
zZPlAEX^!0sAR*46P5>!!CxE251t2ZH04O0o1C$a!0cfo^#^9D-qBVg7)@!hzrs@G`
zV|k^jez9KSoJ_D69<>cuQ$6R;Z|tuBwtP<k%M@LNKjSO~u_(nQAQk{6ro#e|hHwH%
zLU;kBAc6oA5K({-gfY`?*L6GgIkzPNaB}xA3Lj0QuFn<cxa7Tn521V#rkJ^GBbxd7
kFA!O=Ustp7Wv#2(5hfPw4ddT}jsO4v07*qoM6N<$f}XIUod5s;
new file mode 100644
index 0000000000000000000000000000000000000000..3a7b9688c3c1bec62ea06473ebf95f4a21cd37c0
GIT binary patch
literal 396
zc$@)@0dxL|P)<h;3K|Lk000e1NJLTq001BW000~a1^@s60K&Z@00001b5ch_0Itp)
z=>Px$MoC0LR7efQm(6a%Fbv0Smr6Xr#9@!YZ4%?eBkeMd+hr5)GEHcjcH()sL)t|&
zi#HG!5+lw>$)QSI$N!(*G-&}6+h+4UZkqP3ZSA`;W~vQ`+6kxrERKk`dwb^`&WFSL
z>(uYun9kh@wIf0$d<oG#HI1DK+rQmp03up=g-)obAd&&<x?XYFV<D2)z#(%kJD1;&
zWl|T{L^c2hiGj!p5Cf4NKnqa>Km$<>AQYk~KnMhGxAv~8;1R&x@Pr;)M}!aP50Q^6
zi0|{nwcIp%O#UcEyB$0O;QDClt>+&Byj*_~mdrO~Yc5uS5OGev2tcTK5de*Nb^xt-
zR)84sYyh$1SpbZ&_eAd12a~(%#ZNI7=a&2y__Ji`&yvw!xZi8AID1QK5hJ|oTsIKj
qDseF{zH6<W_`jo1t^_|0ZKNNpJ?KZne2^vp0000<MNUMnLSTY1wy4Vh
new file mode 100644
index 0000000000000000000000000000000000000000..a87c4672cc230c2caf3796ad7be69c8e5a246d2c
GIT binary patch
literal 463
zc$@*x0WkiFP)<h;3K|Lk000e1NJLTq000~S000~a1^@s6at+^<00001b5ch_0Itp)
z=>Px$iAh93R7efImd#GXFbv1zmT1!+pfAG#P9X6<JHd^Q0}sT36Blkg2&#782hnO`
zwb9ZnPQ5HJX-eYS{yCZR??7dK)@yTF*Xmv=Y-A~*-S5>i$efS8c02PXhq-uYD>wb0
z5u0ov9gkAbo?2-3k#eBz*4zN#lYJiDOi|zzjEam_!BwBKGq5g<DFWnRi11Jxn1apc
z`n@RdR2adtk94y!SCMY)=on)=b34rjR+U-?1y91x+96_h;i|S{0_Kau8PZnQ)e9o7
ztlE5c9W1$HJSb8x-ilP8gqXfG_o^OEjWO2}zfn+R0b|vNb~e*@p`Y!>TiYOy);|2^
zalbGwwzdiU_nANM-G|oqV6ilETe3^JduBWIRgM^YvOo?-_e^X3F-{|2MS&?8*Nsx-
z5%4czRFv(~pRb@gdZqY<BrbIjDOmc6ox5)<3L}7@+yUKK97c&_N9usg*h|!6p+6ai
zq&c-iCJ>wc4>0q1!fb)QnooEacw8OST$*iAeW`ok_X}#W)JK8{;QRmp002ovPDHLk
FV1mlA(c}OC
new file mode 100644
index 0000000000000000000000000000000000000000..245afef1191b98f9d8592a17a0a422d004d8373d
GIT binary patch
literal 551
zc$@(z0@(eDP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800001b5ch_0Itp)
z=>Px$;Ymb6R9Fe^RWVM(KoGn$wksY$Ma>hCcmM@ekSHjqphWN%5I^7n)I0!*Cxns+
zi4RbnFFAHFC#~1(#6BmXA=2sgc6VkryY|_b#Gm*6#5w<t1v`-@4Mu{Ks`AdcDqz8e
zFO6*=N{Vl_h%WK16rqWu^?Vc?8%LKo{L5kkr>m#;5$Kbnv#;<DAs&*uLbeX45T;<%
zV#W}S!TuC8nt)i6Ig)`&9|v=30KC`mEBw7&z{X1|?&`JOB@R$8r6oyGnD4v@OX4RX
zn5Pgzq4AVuVKskWU)P_o)>hV<iN)vCn6TePxTykaJv+;|FskBb&8Ci>Q42qLOJT!@
zn1<m#sgYS5E{(A>EVP6tYc`GRp2oE&WAGs+{qjs2r&Pp8y~0&%zH(-A1TroKR^`ih
zV+4|H8|VK5Mt6W7s$;Cwag8n@RXF1EXr%7+>OH4of&23gv<jdL;*0+y?b6}#Wwyjh
zZeUvl5a^AQdOufhKAxl55C^sy3)AMA?qBI}Zhm9T;!gV4bIxwda;H&Ls{pDzqmRl9
zJzR(D5v^J1RejC#{D{V|;JmF7Ab}Fk0pN*a>|b%>Y>I=k)qyC4PE^(6nlKlXc0lLd
p80)jw4_ufM&0|qy51Kf5z5!BD3ixy>fC~Ts002ovPDHLkV1m>1{2BlN
new file mode 100644
index 0000000000000000000000000000000000000000..a8c322e439caf21bf08fecd9cae5603c0e4658d4
GIT binary patch
literal 459
zc$@*t0W|)JP)<h;3K|Lk000e1NJLTq000~S001Be1^@s60ks%H00001b5ch_0Itp)
z=>Px$g-Jv~R7ef&mqAX$Fc3vOrg4RoB@zeV3asD=EP!LM;sCIu2VliDV8ICxta^nW
zpc2bSZ5@c2-^P($qPV0^B&2vzdot5`o|!lrlPHHVhP3{^A}TJ6LYxqZL#t~u8zUA{
zikUI;MX7^lA~Ntp_+i-5YL!1Q<P>u3!SLyLoZK_?lMorhp1OkB&6m&{xk+O;ky#jK
z1O(OyHDh`;Sn;8?o}_6yuO7BoWLb8sl)7WzXZG)4(Q>KZ7*f3;d9E+^g;@ZgNupk@
z%<zSDVNk?^)%gNTT6$meC<NkqK5{C~Lw3+}1n*q8+a}w{5pE856EGNIXva;?>vWML
ztV8(Ef)Nfi^b;1Ah8l)*<XH^oP>5FNaF=hUmuW|6`Id%j<uJTuFv5TTEp3@nFH3(C
z`Uj%1akq%Z$CdY4Z~Iy|QE10qr)cfA4PE`NYxsaK*B&hHy1%Z4C_II06n8Br5*G~)
zbsE?4Z*O3L#eFFmTr|3b!gqO@G3(nC_S4sO?FU2+tWQPa*=7I$002ovPDHLkV1n|L
B$F%?e
new file mode 100644
index 0000000000000000000000000000000000000000..204d6f6c68b4af754a96b9a2eed2894993956c74
GIT binary patch
literal 1007
zc$@+60}%X)P)<h;3K|Lk000e1NJLTq0015U000~a1^@s6cK8pe00001b5ch_0Itp)
z=>Px&sYygZR7efAR!c}!Q5e4G+$Uy132CjOA|fga#f+dx0wW6A>LQ`Xx>ZCJRBDST
z0yjbsv?$0$&_ZY<E-V6#Y!QjAqFO{vQA#@A*WA<h&+RzpPIG5&ng?di|9+kSp8qf{
z!}2_DM-;LBjA^Zmu}16-Q6wV9#0>DyFfl2Fn6PboD$QIz9~{ti?K1HT1?>h)6NDiS
zhaHUZ(~#MgCRawE7J@ynZDRxh36<x0!Bb5W>th<rRdfueO%UuyW_wiStgsN;OWQVk
z;rxr#@jU;PglXq0La^`qZE!lYRHtMEx@|!a4#8G4;gwb*V+giDZ2%cNsxTsVk;P~f
zX=9FKOoKOrpKx8b$u!NKIPb&IIS5+99&}vJweyx`O_pc8C^$baHtKpY)4HTnKJNQ&
zUwwW3SCw84FDxu<(slhBob6P32zu5ujV|A(GcK*7<G7K6yC~6K$$~;CM06XS`dHFx
z?XY8^YL}4s2~`$$(e)atSz5(2E))u#s#9X4I|u&7Dd`|sA3E1z>mlKCl{+Q6blf9_
z;$4j3lX#S*Wyf&tg9zheH4Pqj9@{E~5Zx~{L%+nAvQy^xjQgtT8tBw^ltx`opg6A*
zs==ijNnQ@IG!m$~sMN_r=i0NX8fDD*8caGZ6RC)Dlw^a#5jdZ>3cf-h%fT^UE3KpC
zKT+mT;#qdO@X<)QEV8i-%aM+uD&V}6r>!zm;JP~V1z5*Y*r{ZWCio$_oU_%q1QNkW
z-v8d=SS((J<P@J*))Ba@Sg5NL;|gbdXjv9BDsxPaaa9&q<w<0|N~Ns?%<=iWL07&n
z85a${A6_WoD+A$kVnWy1{iJzu9JBUFl9nAq#kS+w)D0V()3oGR)G;sbL1>p0L_jVc
zcsDWlhb67n4u?8kFXwO{oPjLa4lK*;f~^nby3|}W&M+CnEBLhXQUFFA#-gh*)C)NA
zIFK^xJ~ubl2w9rxXUXIrp6UCAR#i^IQlN<E^L{(--a9}nDL^{{o5k~H7>)QGJuyYq
zAUXnC<GSH)&^v&2f@Bk2S@f9bb{t3Pp_rR+OeB2A`*4HZLgcAgqB1V{RINmSvB~%!
z!QovdF4B8TrAxS2YKhPe!HFmey8)uxD=#>u$6%^c@TS5r=t*-*R{zSFh_vEH@s47M
zoC3O~NUZtCKB4S`hGC2%<Ej%m)v@$}09X(N&GcXZtpx@fL0bn{!1i~rzX5&?cnlf7
dtL0GI{SB2mcL8Z9sU-ja002ovPDHLkV1gt1(8B-#
new file mode 100644
index 0000000000000000000000000000000000000000..0387776814a6fea748f8335bd33fdb8fdb8e3546
GIT binary patch
literal 946
zc$@*U15NyiP)<h;3K|Lk000e1NJLTq001HY001Hg1^@s6I!6n_00001b5ch_0Itp)
z=>Px&Y)M2xR9FesSiNf$K@^{v?0qFiN>R|lAf&YNBUXxHA%YRq6#6ejllW1^E}alW
z@juW;EJ8>nR%r}aSf&doBBl^*!rkuO?)ZDR?C@r9=5|-jfdj|B_vZKB{N~Na8%~J-
zxoNFi_)YxFImj}>y4~)qQtGnSVopkV0wmhx2fd5Wu2SN29M`s5E%~)fJQrpp5e#^$
z*X!NKfEQfOd7G4CyWj7xPfkvL%l8%OULs-Gzb!=a2mvZB0Z4a*P|uppV6$j&-tQz5
zMbR<>-sQlma+2uhtybf8S-&6;48!n_n}pm$hBmNVJB>!;2l)Ye6no}8GBA%FGs9yk
zC6};Fzk(px;&z{GWrX%b6!qQ!%$K8&LDuW_`a2AoxB|gXA&a+!kSpjnlLP)Bio%6<
zyFDQ8^37~26X+X;y$ASMB(MP&k%6~9668mHDMl<p1@W|j;8YOQmNI?R*ASs2ib3aW
z@E{YPY@1(0)_~RP908J-K<Eg!xnx5G>wLuq$URyP+g7ZlKD3`qo9K3X*No;73=t`H
zE*r_lsO9j)8!QuTYTl1bpXRztW<=C+4nR70xL!rh`(i?~Mg9XKaHQHXxVAHg?1*N1
zm2ch`8JQ~b&oUAf0sp2SldKi_4~QUjF)lGGV5ZS!Wt55ne2>{Kdf(QEwJamlv&*|d
z4makXHTa(6o?6Q<TzAQa2$gahpyrWM({K0rwbV!5<OrO|k6d@jW*~Y`*Z@6~UfZ^{
zNP`cmwm!*lNf_2YFx@E{BJ`-i?%uXhas`3U*fzfg>{%(*vW?K2)6?>&Z5!4M5$d8x
zP5PcNzySKov?BYLiIxMH1yr3EkgcMJoA#B7HbStfFX0gI1_C}E_8IvMz@D&{BXdu%
zQCFMI+WXAl`wkHyAYNzpa7~x0n!doyUW$y92nE41UB@fyF;ZQ4E3!eU)*Qg61sh-X
zLNXl8;|Y3M(W3@IX~)M_r(40JNpI9@0gk;~1%yAM6prv3s_<2}D>j3#gWEyo2$gcG
zqL?wgTc%*cwXOH*vZ8x}jwnAJG$;*@IDE3+%#<R+NmY@nkU3N$M7k`QLnl&}%vgw&
zAu~22qsSyl{A8>|{AA>JezXX8=#8%X{5_*}l8ikg*-Sf~&PDvy@eoBdj$^s@8?fq=
U0u$IdQUCw|07*qoM6N<$f>N=;>;M1&
new file mode 100644
index 0000000000000000000000000000000000000000..bd84a7f8996777b5a58173e643d48517e2519e75
GIT binary patch
literal 575
zc$@)00>J%=P)<h;3K|Lk000e1NJLTq000~S001Be1^@s60ks%H00001b5ch_0Itp)
z=>Px$`AI}UR7ef&mc35HFc8OWw@pePpgaJtz=i}2h=B!o4<?2#v|G#bzyK2LZ0t;x
z7?6-US54CpA9qdNx{l+<O6f$TDChh5|8lO~m@&^QijtE!PM+wFqUhAKoN=FmBuUPs
zgaOvn7IhMUcbm<|YgwJrKnqMUyr89k4wyG|Bd`R_3+e=Vz)C}f$~2z^FlpxDSoaCe
zp+B7_=a#&=%L*)l;fm~;LJMDMXby<5V`J$PgH~b>m;Z|iBwrEKwoh|FDcKE*s(t2!
zDR>c7i2AL{QO_KZF_@|#J_|e3a^|KD3V^R~TsGi6=6oRdQ_8esn?^%pIiy@6cn530
z0pJVm{xY~QoZG@org0q4-gSQ%28a51lWpm6Q%SY>Kd{>TS*mwGrISf=gkSGxy2-Y@
zR3(?G&k2P4rk$zsQ5ZHZTm;{3Vd~?QDi~pO+lBRs>6*~q{cq^=u30W0t!i|8<#k!!
z9i}P6QyYQ!D6?Ji`B**ga(h~>#v5ih7nV!GyF-^)nV0}zk)AjnkN5R)72DJzmJoss
zb<rRQ?#x6zUe+cJ($e#Zg&Y6p8b9o70X=EEwit*Ys6Ak-Yai9^LNYaC5DU+d9Psa~
z`<GDCCI+#VM+`iJ@YyWA;#^+h(dU43wpXQ7gx~^ULjdteoe_-megVZG8x;=DGu{9I
N002ovPDHLkV1jwB23-IE
new file mode 100644
index 0000000000000000000000000000000000000000..3259fadba744fabc6af74cae074001ecd3fdd229
GIT binary patch
literal 476
zc$@*;0VDp2P)<h;3K|Lk000e1NJLTq001BW000~a1^@s60K&Z@00001b5ch_0Itp)
z=>Px$mPtfGR7ef&S4&RAKn$HpLV{4#6%u>SfIxynkbAJ;06-TA4$uYnNDl!LpEIy$
z!6u5TOi&o!1Ev|O4$vwYgw$-tu^m7A*-afOJ}<4cY?|h<X<jp}#kQ1U!`Qkw5p#l=
zk3#4?Ns`>eloX1h*o@=#b2#i8L!T#bZmVi-I2g!h$;y>_x$*^W3S$y+93KUw-8VRs
zKuh+NQdz{Fo2+;unVY(<FVi%Avh^-msrrGoB#C!iKGc_GxrK^P0KDJ&$t>W&wF)5?
z0k@y~NoGNeZTk^BLd9RE{kN6dfovHdBLqIMb-=hr^~a12#-=7>2h+P=1*u)(BbQ-W
zJu6-0Sx*eOQ|g?7?`B|L8lD(f&A>eJKXkp$fcgEq;f3gV2Hd?jNp;S^zk3h#+yX<i
z`&=dP_YB~_dt!Hpn~Qzlr92y(*a2P^Se4t0YtyV_Yh7M4E14aE*w}~_c0ze-8+^%O
z7+eIXcnm7;e1RGqVBUveI7SPkuIp;(GYNtN^NiT<Uq;Nz*QXh1&sjOaiTeimPO0){
ScYI+00000<MNUMnLSTYgj?$C>
new file mode 100644
index 0000000000000000000000000000000000000000..716a5112615f9b0a43d4b1fe58c4b50471e7b530
GIT binary patch
literal 1214
zc$@*g1VQ_WP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800001b5ch_0Itp)
z=>Px(cu7P-R9Fd}mraNqMHI)odb)dhbU#%#E<`*yQOGIBAW?GDgT_lpHm)BS{DOFp
zAS57oUQogw;z30)Bql`k6i*&RQ9SEOWH+c7$-1b^#v#+w)7$0m&1`k5dwX`Kr=WOM
z@8kboy?RyEt(-AiyWM`!b-m}sJWZ2}jYi}5aiG*VM(gYA6VubPR~<+1>D#NnHa9np
z&&|!Xs^Ym-4Mcx(a%SO<bK&Sc@Q%x<YO5T8*7|OxoM(%U;4O-*$R9SZ96%Ix7jQOJ
z1QuSm+pV01N&#%IezEA>%+u6)u4)!41t2T5SFg3xl5PUn&cZP>ABBz_04ux8aa3;g
zuIqd%J?}_K7SJ87jU0fi9^h#MD=YVX|B7@w3!+n{7CZxJQ$XZ?*qbCtlkq<3?C(KR
zoHbT{St->^e-y=65WHf9=$`C!I{SfHrLTmcw}R|X^i!i_Xb-a0YTeID4#RAs)C2(P
zghr`I#j)>uPecC`839gqyU8`^L{Znw$x;O7b+(aU($ydczQKM?-M$?k^gOkUacMRT
zfK37WC=7!SY#v#79S1Mlyxqn)C&Btn*Ylhc6`X5U@N2#9UoL{fqZsvX@X;CG#3u`1
z@EB|Wy2FA9Hzi$4>D4q%S5a6YZP(#PJCtF-m+d$TUKq#mLyY&iu1gK6CNW7JWd&^P
zwN5t_f_bX;0%^U+2>R4rs@J{G^Stq9olbI;eLrhkvt9pEcQ3d^ev=ixVIQTwVtR&a
z_X*o*oN*LIPvZQHZ7aUg)IWvqwJi6f?Er~9FDW$2C?s23&RdO!|GnW=q3w3}P_5>?
z2WD2_V6uh!6x;ceU}XWwgspg#=+4;&uscfm7^ojbXVezQ`heEm_tCE#8(9#kKTYa?
zFudGNC<5+)cM#f@3_!9>DjzXM!)RYOSw=5&E|`LCI~SZ>0Ky1E|0{HtWNaE4nNZ4o
z+subi(G{D#o?hx>=eauq5OKX;|AJIqvQ?S?ZO?ZbvyK1Qa={Wzn`g$Q0f>;|%bwY7
z<v)zkaH?{;VD+x-GP{8RxUSl38))s`u;;stDYjeyuB#syq(3kKZopgsJY+dg`7-AI
ze@(iKZ3jhN0?J|8y4m@(nKI@ICF(neftRC~0g5Z+xboGbUS!<6UT0=zk8zJ&pu#_s
za}K=`$K4DPtbqaK?g3)~a07tv%v{bd&+lQJ9O2-cB(VF8EKe1Msy+^a+BNLIMOHKN
zAn+dpr)}njmIlB%ewd?_y?C-Jc{l){H-@`YeG~gx$(GU6+CLG7@-2{Wr8S^+Etj%B
z&`#$B){>rwl$n~hoeM|nq_hxA1E|#oS8WfTjBvI;VOx$!m$76?WP=)*xkVYh(g4y_
z-D?yIG@+obMv?ankI8wQ-jXh3;fW0Wq+rvVat+Ux@duoOtzQbaG#``d%OLPR#Nk>Q
z(A1QY+wWace=&}eS4sL)%&i5gpUdn@ix3c(Z-JNi@_ih~E93lrZ~wk85=fIczUJfR
cQdt2111ksX+H^JlN&o-=07*qoM6N<$f<`t<EdT%j
new file mode 100644
index 0000000000000000000000000000000000000000..c27fa34325769e25d70d4135321d9e800d52f79e
GIT binary patch
literal 380
zc$@)z0fYXDP)<h;3K|Lk000e1NJLTq001BW000^Y1^@s6)|*~G00001b5ch_0Itp)
z=>Px$Hc3Q5R7eeDWWWNxeEA~I%F3Pxlrm;u_%DJ*2?;`sZ-9!={{H=Q5)Tj0OLUEl
z=mH?iSy<SXGcq#pq03Ri|No!i)1N=TBGDbegl;Iv=hU_wWCzGhXsDuCiQxdCEHKz<
z1~AOV;s8qH9G~Mc&Bo#Yd<IZoZqxyzAwaVb0OtE+zkmPoW@l$J0bvjuB!-@hF-pRp
zKYyJ;S40jUWFdN~2P$RJ#b_1+FpGZu`ZW=RL7sq#A$y1gnL`UUunw@sXD-b`0H3AE
zas%!FmT%vFTQf5=R0HdMF=Uq!%Lb)vU>vt%i(g{QV4}owkOh=j4$@C?B82%Il+y7f
zIBeOQk&*ET)8D@gt-$8OE0Al3B>?#xo9|(s9q?Q*>VN?c0gAIBEHUAtfd$o3U@rTQ
aOCA7`17XArVeujW0000<MNUMnLSTX=dYrca
--- a/widget/cocoa/moz.build
+++ b/widget/cocoa/moz.build
@@ -49,16 +49,17 @@ UNIFIED_SOURCES += [
     'nsMenuX.mm',
     'nsPrintDialogX.mm',
     'nsPrintSettingsServiceX.mm',
     'nsPrintSettingsX.mm',
     'nsSound.mm',
     'nsStandaloneNativeMenu.mm',
     'nsSystemStatusBarCocoa.mm',
     'nsToolkit.mm',
+    'nsTouchBar.mm',
     'nsWidgetFactory.mm',
     'nsWindowMap.mm',
     'OSXNotificationCenter.mm',
     'RectTextureImage.mm',
     'ScreenHelperCocoa.mm',
     'SwipeTracker.mm',
     'TextInputHandler.mm',
     'VibrancyManager.mm',
@@ -100,40 +101,51 @@ if CONFIG['MOZ_ENABLE_SKIA_PDF']:
         '/gfx/skia/skia/include/core',
     ]
 
 RESOURCE_FILES.cursors += [
     'cursors/arrowN.png',
     'cursors/arrowN@2x.png',
     'cursors/arrowS.png',
     'cursors/arrowS@2x.png',
+    'cursors/back@2x.png',
     'cursors/cell.png',
     'cursors/cell@2x.png',
     'cursors/colResize.png',
     'cursors/colResize@2x.png',
+    'cursors/forward@2x.png',
+    'cursors/fullscreen@2x.png',
     'cursors/help.png',
     'cursors/help@2x.png',
+    'cursors/home@2x.png',
     'cursors/move.png',
     'cursors/move@2x.png',
+    'cursors/readermode@2x.png',
+    'cursors/refresh@2x.png',
     'cursors/rowResize.png',
     'cursors/rowResize@2x.png',
+    'cursors/search@2x.png',
+    'cursors/share@2x.png',
+    'cursors/sidebar@2x.png',
     'cursors/sizeNE.png',
     'cursors/sizeNE@2x.png',
     'cursors/sizeNESW.png',
     'cursors/sizeNESW@2x.png',
     'cursors/sizeNS.png',
     'cursors/sizeNS@2x.png',
     'cursors/sizeNW.png',
     'cursors/sizeNW@2x.png',
     'cursors/sizeNWSE.png',
     'cursors/sizeNWSE@2x.png',
     'cursors/sizeSE.png',
     'cursors/sizeSE@2x.png',
     'cursors/sizeSW.png',
     'cursors/sizeSW@2x.png',
+    'cursors/star@2x.png',
+    'cursors/tabnew@2x.png',
     'cursors/vtIBeam.png',
     'cursors/vtIBeam@2x.png',
     'cursors/zoomIn.png',
     'cursors/zoomIn@2x.png',
     'cursors/zoomOut.png',
     'cursors/zoomOut@2x.png',
 ]
 
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -80,16 +80,18 @@ typedef struct _nsCocoaWindowList {
 
 - (void)disableSetNeedsDisplay;
 - (void)enableSetNeedsDisplay;
 
 - (NSRect)getAndResetNativeDirtyRect;
 
 - (void)setUseMenuStyle:(BOOL)aValue;
 
+- (NSTouchBar *)makeTouchBar;
+
 @end
 
 @interface NSWindow (Undocumented)
 
 // If a window has been explicitly removed from the "window cache" (to
 // deactivate it), it's sometimes necessary to "reset" it to reactivate it
 // (and put it back in the "window cache").  One way to do this, which Apple
 // often uses, is to set the "window number" to '-1' and then back to its
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -30,16 +30,17 @@
 #include "nsNativeThemeColors.h"
 #include "nsNativeThemeCocoa.h"
 #include "nsChildView.h"
 #include "nsCocoaFeatures.h"
 #include "nsIScreenManager.h"
 #include "nsIWidgetListener.h"
 #include "nsIPresShell.h"
 #include "VibrancyManager.h"
+#include "nsTouchBar.h"
 
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "qcms.h"
 
 #include "mozilla/AutoRestore.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
@@ -3159,16 +3160,21 @@ GetMenuMaskImage()
     // Turn off rounded corner masking.
     NSView* wrapper = [[NSView alloc] initWithFrame:NSZeroRect];
     [self swapOutChildViewWrapper:wrapper];
     [wrapper release];
   }
   mUseMenuStyle = aValue;
 }
 
+- (NSTouchBar *) makeTouchBar
+{
+    return [[TouchBar alloc] init];
+}
+
 - (void)setBeingShown:(BOOL)aValue
 {
   mBeingShown = aValue;
 }
 
 - (BOOL)isBeingShown
 {
   return mBeingShown;
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsTouchBar.h
@@ -0,0 +1,58 @@
+/* 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/. */
+
+#ifndef nsTouchBar_h_
+#define nsTouchBar_h_
+
+#import <Cocoa/Cocoa.h>
+
+#include "mozilla/RefPtr.h"
+#include "nsIDocument.h"
+
+/*
+* Our TouchBar is its own delegate. This is adequate for our purposes, since the current
+* implementation only defines Touch Bar buttons for the main Firefox window. If modals and
+* other windows were to have custom Touch Bar views, each window would have to be a
+* NSTouchBarDelegate so they could define their own custom sets of buttons.
+* NSTouchBarDelegate implements `makeTouchBar:` (in lieu of `init:`) and `makeItemForIdentifier`.
+*/
+@interface TouchBar : NSTouchBar<NSTouchBarDelegate>
+
+- (id)init;
+
+// Create new NSTouchBarItem. Reads the passed identifier and creates the
+// appropriate item type (eg. NSCustomTouchBarItem).
+- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
+      makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier;
+
+// Updates NSCustomTouchBarItem, adding a title and image.
+- (void)updateButton:(NSCustomTouchBarItem*)item
+           withTitle:(NSString*)title
+           withImage:(NSImage*)image;
+
+// Initializes buttons from a default set.
+// Could be depreciated in the future if an API is introduced.
+- (void)updateButtonFromDefaults:(NSCustomTouchBarItem*)item
+                      withAction:(NSString*)action;
+
+// Redirects button actions to the appropriate handler and handles telemetry.
+- (void)touchbarAction:(id)sender;
+
+/*
+* Static helper functions
+*/
+// Acquires the active nsIDocument.
++ (RefPtr<nsIDocument>)getXULDocument;
+
++ (void)dispatchSystemFunction:(nsAutoString)action
+                    toDocument:(RefPtr<nsIDocument>)doc;
+
+// Retrieves icons from widget/cocoa/cursors
++ (NSImage*)cursorWithImageNamed:(NSString*)imageName;
+
++ (NSString*)getLocalizedTouchbarName:(NSString*)lookupKey;
+
+@end  // TouchBar
+
+#endif // nsTouchBar_h_
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsTouchBar.mm
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=80: */
+/* 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/. */
+
+#include "nsTouchBar.h"
+
+#include "nsMenuUtilsX.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsIWindowMediator.h"
+#include "nsIDocument.h"
+#include "mozilla/MacStringHelpers.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/Preferences.h"
+
+#define TOUCHBAR_LAYOUT_PREF      "ui.touchbar.layout"
+
+@implementation TouchBar
+
+static NSTouchBarItemIdentifier CustomButtonIdentifier = @"com.mozilla.firefox.touchbar.button";
+
+static NSTouchBarItemIdentifier NewWindowIdentifier = @"cmd_newNavigator";
+static NSTouchBarItemIdentifier NewTabIdentifier = @"cmd_newNavigatorTabNoEvent";
+static NSTouchBarItemIdentifier CloseWindowIdentifier = @"cmd_closeWindow";
+static NSTouchBarItemIdentifier FindIdentifier = @"cmd_find";
+static NSTouchBarItemIdentifier ViewBookmarksSidebarIdentifier = @"viewBookmarksSidebar";
+
+static NSTouchBarItemIdentifier FullscreenIdentifier = @"View:FullScreen";
+static NSTouchBarItemIdentifier ReaderViewIdentifier = @"View:ReaderView";
+
+static NSTouchBarItemIdentifier AddBookmarkAsIdentifier = @"Browser:AddBookmarkAs";
+static NSTouchBarItemIdentifier HomeIdentifier = @"Browser:Home";
+static NSTouchBarItemIdentifier BackIdentifier = @"Browser:Back";
+static NSTouchBarItemIdentifier ForwardIdentifier = @"Browser:Forward";
+static NSTouchBarItemIdentifier ReloadIdentifier = @"Browser:Reload";
+static NSTouchBarItemIdentifier OpenLocationIdentifier = @"Browser:OpenLocation";
+
+// Used to tie action strings to buttons
+static char actionStringAssociationKey;
+
+#pragma mark - NSTouchBarDelegate
+
+- (id)init
+{
+  if ((self = [super init])) {
+    Telemetry::ScalarSet(Telemetry::ScalarID::TOUCHBAR_ENABLED, true);
+    self.delegate = self;
+
+    // Assemble button identifiers by appending actions to input type
+    NSTouchBarItemIdentifier BackButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:BackIdentifier];
+    NSTouchBarItemIdentifier ForwardButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:ForwardIdentifier];
+    NSTouchBarItemIdentifier ReloadButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:ReloadIdentifier];
+    NSTouchBarItemIdentifier HomeButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:HomeIdentifier];
+    NSTouchBarItemIdentifier FullscreenButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:FullscreenIdentifier];
+    NSTouchBarItemIdentifier FindButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:FindIdentifier];
+    NSTouchBarItemIdentifier NewTabButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:NewTabIdentifier];
+    NSTouchBarItemIdentifier ViewBookmarksSidebarButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:ViewBookmarksSidebarIdentifier];
+    NSTouchBarItemIdentifier AddBookmarkAsButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:AddBookmarkAsIdentifier];
+    NSTouchBarItemIdentifier ReaderViewButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:ReaderViewIdentifier];
+    NSTouchBarItemIdentifier OpenLocationButtonIdentifier =
+      [CustomButtonIdentifier stringByAppendingPathExtension:OpenLocationIdentifier];
+
+    int layoutPref = [TouchBar getLayoutPref];
+
+    switch (layoutPref) {
+      case 2:
+        self.defaultItemIdentifiers = @[BackButtonIdentifier, ForwardButtonIdentifier,
+          ViewBookmarksSidebarButtonIdentifier, ReaderViewButtonIdentifier, FindButtonIdentifier,
+          AddBookmarkAsButtonIdentifier, FullscreenButtonIdentifier, NewTabButtonIdentifier,
+          NSTouchBarItemIdentifierOtherItemsProxy];
+        break;
+      case 1:
+        self.defaultItemIdentifiers = @[BackButtonIdentifier, ReloadButtonIdentifier,
+          HomeButtonIdentifier, OpenLocationButtonIdentifier, FullscreenButtonIdentifier,
+          NewTabButtonIdentifier, NSTouchBarItemIdentifierOtherItemsProxy];
+        break;
+      default:    // case 0
+        self.defaultItemIdentifiers = @[BackButtonIdentifier, ForwardButtonIdentifier,
+          ReloadButtonIdentifier, OpenLocationButtonIdentifier, HomeButtonIdentifier,
+          NewTabButtonIdentifier, NSTouchBarItemIdentifierOtherItemsProxy];
+        break;
+    }
+  }
+
+  return self;
+}
+
+- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
+     makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
+{
+  if ([identifier hasPrefix:CustomButtonIdentifier]) {
+    NSCustomTouchBarItem* item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
+    NSButton* theButton = [NSButton buttonWithTitle:@""
+                target:self
+                action:@selector(touchbarAction:)];
+    NSString* actionString = [identifier substringFromIndex:CustomButtonIdentifier.length + 1];
+    objc_setAssociatedObject(theButton, &actionStringAssociationKey, actionString, OBJC_ASSOCIATION_RETAIN);
+    item.view = theButton;
+    [self updateButtonFromDefaults:(NSCustomTouchBarItem*)item withAction:(NSString*)actionString];
+    return item;
+  }
+
+  return nil;
+}
+
+- (void)updateButton:(NSCustomTouchBarItem*)item
+           withTitle:(NSString*)title
+           withImage:(NSImage*)image
+{
+  if (!item)
+    return;
+  NSButton* button = item.view;
+  button.title = title;
+  item.customizationLabel = title;
+  if (image) {
+    button.image = image;
+    [button setImagePosition:NSImageOnly];
+  }
+}
+
+- (void)updateButtonFromDefaults:(NSCustomTouchBarItem*)item
+                      withAction:(NSString*)action
+{
+  // if/elseif instead of switch/case since it's all string comparison
+  if ([action isEqualToString:BackIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"back"]
+             withImage:[TouchBar cursorWithImageNamed:@"back@2x"]];
+  }
+  else if ([action isEqualToString:ForwardIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"forward"]
+             withImage:[TouchBar cursorWithImageNamed:@"forward@2x"]];
+  }
+  else if ([action isEqualToString:ReloadIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"reload"]
+             withImage:[TouchBar cursorWithImageNamed:@"refresh@2x"]];
+  }
+  else if ([action isEqualToString:FullscreenIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"fullScreen"]
+             withImage:[TouchBar cursorWithImageNamed:@"fullscreen@2x"]];
+  }
+  // Not yet receptive to whether or not the page can be opened in Reader View
+  else if ([action isEqualToString:ReaderViewIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"readerView"]
+             withImage:[TouchBar cursorWithImageNamed:@"readermode@2x"]];
+  }
+  else if ([action isEqualToString:FindIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"find"]
+             withImage:[TouchBar cursorWithImageNamed:@"search@2x"]];
+  }
+  else if ([action isEqualToString:NewTabIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"newTab"]
+             withImage:[TouchBar cursorWithImageNamed:@"tabnew@2x"]];
+  }
+  else if ([action isEqualToString:HomeIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"home"]
+             withImage:[TouchBar cursorWithImageNamed:@"home@2x"]];
+  }
+  // Not yet receptive to whether or not the page is already bookmarked
+  else if ([action isEqualToString:AddBookmarkAsIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"addBookmark"]
+             withImage:[TouchBar cursorWithImageNamed:@"star@2x"]];
+  }
+  else if ([action isEqualToString:ViewBookmarksSidebarIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"openBookmarksSidebar"]
+             withImage:[TouchBar cursorWithImageNamed:@"sidebar@2x"]];
+  }
+  // Special handling for the wider Open Location button
+  else if ([action isEqualToString:OpenLocationIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+             withTitle:[TouchBar getLocalizedTouchbarName:@"openLocation"]
+             withImage:[TouchBar cursorWithImageNamed:@"search@2x"]];
+    NSButton* button = item.view;
+    [button setImagePosition:NSImageLeft];
+    button.imageHugsTitle = YES;
+    [button.widthAnchor
+      constraintGreaterThanOrEqualToConstant:252]
+      .active = YES;
+    [button setContentHuggingPriority:1.0
+                       forOrientation:NSLayoutConstraintOrientationHorizontal];
+  }
+}
+
+- (void)touchbarAction:(id)sender
+{
+  NSTouchBarItemIdentifier actionIdentifier = objc_getAssociatedObject(sender, &actionStringAssociationKey);
+  if (!actionIdentifier) {
+    return;
+  }
+
+  nsAutoString action;
+  mozilla::CopyCocoaStringToXPCOMString(actionIdentifier, action);
+
+  Telemetry::ScalarAdd(Telemetry::ScalarID::TOUCHBAR_BUTTON_PRESSED, action, 1);
+  [TouchBar dispatchSystemFunction:action toDocument:[TouchBar getXULDocument]];
+  return;
+}
+
+#pragma mark - TouchBar Utilities
+
++ (RefPtr<nsIDocument>)getXULDocument
+{
+    nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CID);
+
+    if (!wm)
+      return nil;
+
+    nsCOMPtr<mozIDOMWindowProxy> recent;
+    nsresult rv = wm->GetMostRecentWindow(nullptr, getter_AddRefs(recent));
+
+    NS_ENSURE_SUCCESS(rv, nil);
+
+    RefPtr<nsIDocument> doc = nsPIDOMWindowOuter::From(recent)->GetDoc();
+
+    return doc;
+}
+
++ (void)dispatchSystemFunction:(nsAutoString)action
+                    toDocument:(RefPtr<nsIDocument>)doc
+{
+  if (doc == nil)
+    return;
+
+  dom::Element* aDomElement = doc->GetElementById(action);
+  nsMenuUtilsX::DispatchCommandTo(aDomElement);
+}
+
++ (NSImage*)cursorWithImageNamed:(NSString*)imageName
+{
+  nsCOMPtr<nsIFile> resDir;
+  nsAutoCString resPath;
+  NSString* pathToImage;
+
+  nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(resDir));
+  resDir->AppendNative(NS_LITERAL_CSTRING("res"));
+  resDir->AppendNative(NS_LITERAL_CSTRING("cursors"));
+
+  rv = resDir->GetNativePath(resPath);
+  NS_ENSURE_SUCCESS(rv, nil);
+
+  pathToImage = [NSString stringWithUTF8String:(const char*)resPath.get()];
+  pathToImage = [pathToImage stringByAppendingPathComponent:imageName];
+  pathToImage = [pathToImage stringByAppendingPathExtension:@"png"];
+  NSImage* image = [[NSImage alloc] initWithContentsOfFile:pathToImage];
+  // A nil image will fail gracefully to a labelled button
+
+  return image;
+}
+
++ (NSString*)getLocalizedTouchbarName:(NSString*)lookupKey
+{
+  NSString* localizedName = [[NSString alloc] initWithString:lookupKey];
+
+  nsCOMPtr<nsIStringBundleService> sbs = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
+  nsCOMPtr<nsIStringBundle> bundle;
+  nsresult rv = sbs->CreateBundle("chrome://global/locale/touchbar.properties", getter_AddRefs(bundle));
+  if (NS_SUCCEEDED(rv)) {
+    nsAutoString localLabel;
+      rv = bundle->GetStringFromName([lookupKey UTF8String], localLabel);
+      if (NS_SUCCEEDED(rv)) {
+      localizedName = [NSString stringWithCharacters:reinterpret_cast<const unichar*>(localLabel.get())
+                      length:localLabel.Length()];
+      }
+  }
+
+  return localizedName;
+}
+
++ (int)getLayoutPref
+{
+    nsresult rv;
+    int layoutPref = 0;
+    nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+    if (!NS_FAILED(rv) && prefService) {
+      nsCOMPtr<nsIPrefBranch> mPrefBranch;
+      rv = prefService->GetBranch(nullptr, getter_AddRefs(mPrefBranch));
+      if (!NS_FAILED(rv)) {
+        rv = mPrefBranch->GetIntPrefWithDefault(TOUCHBAR_LAYOUT_PREF, 0, 0, &layoutPref);
+        if (NS_FAILED(rv) || layoutPref < 0 || layoutPref > 3) {
+          layoutPref = 0;
+        }
+      }
+    }
+
+  return layoutPref;
+}
+
+@end