Add files via upload
2507
build/config/compiler/BUILD.gn
Normal file
BIN
chrome-devtools/chrome-devtools.png
Normal file
After Width: | Height: | Size: 204 KiB |
1
chrome-devtools/chrome-devtools.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" viewBox="0 0 1522 1522"><style>.e{fill:#fff}.a{stroke:#fff}.b{stop-color:#fff}.c{stop-color:#1a237e}.d{stop-opacity:0}.f{stop-opacity:.12}</style><rect id="d" width="1520" height="1520" rx="120"/><radialGradient id="f" cx="15%" cy="14%" r="100%"><stop class="b f" offset="0"/><stop class="b d" offset="1"/></radialGradient><radialGradient id="g" cx="-.2%" cy=".1%" r="136%"><stop class="c" offset="0" stop-opacity=".2"/><stop class="c d" offset="1"/></radialGradient><radialGradient id="h" cx="85%" cy="13%" r="154%"><stop class="c f" offset="0"/><stop class="c d" offset="1"/></radialGradient><radialGradient id="i" cx="41%" cy="0" r="57%"><stop class="c" offset="0" stop-opacity=".15"/><stop class="c d" offset="1"/></radialGradient><path id="a" d="M761 1361a600 600 0 1 0 0-1200 600 600 0 0 0 0 1200z"/><mask id="j" width="120" height="120" x="0" y="0" class="e"><use xlink:href="#a"/></mask><circle id="b" cx="761" cy="761" r="280"/><mask id="k" width="56" height="56" x="0" y="0" class="e"><use xlink:href="#b"/></mask><circle id="c" cx="761" cy="761" r="200"/><mask id="l" width="40" height="40" x="0" y="0" class="e"><use xlink:href="#c"/></mask><use fill="#2879ff" xlink:href="#d"/><g stroke-opacity=".2" stroke-width="5" class="a"><path d="m-199-199 1920 1920m0-1920L-199 1721M1038.5-199v1920m-555-1920v1920M1721 1038.5H-199m1920-555H-199"/><circle cx="761" cy="761" r="390"/><path d="M-199 761h1920M761-199v1920"/></g><circle cx="761" cy="761" r="600" fill="url(#f)"/><path d="M1400 0H120C54 0 0 54 0 120v10C0 64 54 10 120 10h1280c66 0 120 54 120 120v-10c0-66-54-120-120-120z" class="e" opacity=".2"/><path fill="#000" d="M1401 1511H121c-66 0-120-54-120-120v10c0 66 54 120 120 120h1280c66 0 120-54 120-120v-10c0 66-54 120-120 120z" opacity=".1"/><path fill="url(#g)" d="M495.9 675.8 251 431l267.2 458.3a273.7 273.7 0 0 1-22.4-213.5z"/><path fill="url(#h)" d="M820.7 1031 731 1365.6 996.6 901a274.2 274.2 0 0 1-176 130z"/><path fill="url(#i)" d="m962 575.3 334.2-89.3H759.7A273.7 273.7 0 1 0 962 575.3z"/><g stroke-width="40" class="a"><use mask="url(#j)" xlink:href="#a"/><use mask="url(#k)" xlink:href="#b"/><use mask="url(#l)" xlink:href="#c"/></g><path d="M761 481h530v20H761zm242.5 420-265 459-17.3-10 265-459zm-485 0-265-459 17.3-10 265 459z" class="e"/></svg>
|
After Width: | Height: | Size: 2.3 KiB |
BIN
chrome-devtools/chrome-devtools_128x128.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
chrome-devtools/chrome-devtools_16x16.png
Normal file
After Width: | Height: | Size: 609 B |
BIN
chrome-devtools/chrome-devtools_24x24.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
chrome-devtools/chrome-devtools_256x256.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
chrome-devtools/chrome-devtools_32x32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
chrome-devtools/chrome-devtools_48x48.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
chrome-devtools/chrome-devtools_512x512.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
chrome-devtools/chrome-devtools_64x64.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
1275
chrome/app/chromium_strings.grd
Normal file
10
chrome/app/theme/chromium/BRANDING
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
COMPANY_FULLNAME=The Chromium and Thorium Authors
|
||||||
|
COMPANY_SHORTNAME=The Chromium and Thorium Authors
|
||||||
|
PRODUCT_FULLNAME=Thorium
|
||||||
|
PRODUCT_SHORTNAME=Thorium
|
||||||
|
PRODUCT_INSTALLER_FULLNAME=Thorium Installer
|
||||||
|
PRODUCT_INSTALLER_SHORTNAME=Thorium Installer
|
||||||
|
COPYRIGHT=Copyright @LASTCHANGE_YEAR@ The Chromium and Thorium Authors. All rights reserved.
|
||||||
|
MAC_BUNDLE_ID=org.chromium.Chromium
|
||||||
|
MAC_CREATOR_CODE=Cr24
|
||||||
|
MAC_TEAM_ID=
|
BIN
chrome/app/theme/chromium/chromeos/chrome_app_icon_192.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
chrome/app/theme/chromium/chromeos/chrome_app_icon_32.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
297
chrome/app/theme/chromium/linux/product_logo_32.xpm
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
/* XPM */
|
||||||
|
static char * product_logo_32_xpm[] = {
|
||||||
|
"32 32 262 2",
|
||||||
|
" c None",
|
||||||
|
". c #4E7ADB",
|
||||||
|
"+ c #4C78DB",
|
||||||
|
"@ c #4C79DB",
|
||||||
|
"# c #4A77DA",
|
||||||
|
"$ c #4B78DA",
|
||||||
|
"% c #4D7ADB",
|
||||||
|
"& c #4776DA",
|
||||||
|
"* c #4272D9",
|
||||||
|
"= c #4172D9",
|
||||||
|
"- c #4171D9",
|
||||||
|
"; c #4071D9",
|
||||||
|
"> c #3F70D8",
|
||||||
|
", c #3E6FD8",
|
||||||
|
"' c #3D6FD8",
|
||||||
|
") c #4775DA",
|
||||||
|
"! c #4F7BDC",
|
||||||
|
"~ c #4574DA",
|
||||||
|
"{ c #4474D9",
|
||||||
|
"] c #4373D9",
|
||||||
|
"^ c #3D6ED8",
|
||||||
|
"/ c #3C6ED8",
|
||||||
|
"( c #4675DA",
|
||||||
|
"_ c #4976D8",
|
||||||
|
": c #4575D9",
|
||||||
|
"< c #3B6DD8",
|
||||||
|
"[ c #3F6FD8",
|
||||||
|
"} c #4773D5",
|
||||||
|
"| c #4573D6",
|
||||||
|
"1 c #4574D8",
|
||||||
|
"2 c #3A6CD7",
|
||||||
|
"3 c #3C6DD7",
|
||||||
|
"4 c #4670D2",
|
||||||
|
"5 c #4471D4",
|
||||||
|
"6 c #4472D5",
|
||||||
|
"7 c #4473D7",
|
||||||
|
"8 c #4573D9",
|
||||||
|
"9 c #396CD7",
|
||||||
|
"0 c #3B6DD7",
|
||||||
|
"a c #456ECF",
|
||||||
|
"b c #436ED1",
|
||||||
|
"c c #446FD2",
|
||||||
|
"d c #4470D4",
|
||||||
|
"e c #4471D6",
|
||||||
|
"f c #4472D8",
|
||||||
|
"g c #396BD7",
|
||||||
|
"h c #3B6CD7",
|
||||||
|
"i c #6C9AEE",
|
||||||
|
"j c #4169CB",
|
||||||
|
"k c #426DCF",
|
||||||
|
"l c #436FD3",
|
||||||
|
"m c #4370D5",
|
||||||
|
"n c #4372D7",
|
||||||
|
"o c #4372D8",
|
||||||
|
"p c #6BA0F7",
|
||||||
|
"q c #5580D9",
|
||||||
|
"r c #416ACD",
|
||||||
|
"s c #426CCF",
|
||||||
|
"t c #426ED1",
|
||||||
|
"u c #426FD3",
|
||||||
|
"v c #4270D5",
|
||||||
|
"w c #4271D7",
|
||||||
|
"x c #4272D8",
|
||||||
|
"y c #4172D8",
|
||||||
|
"z c #3861BC",
|
||||||
|
"A c #294992",
|
||||||
|
"B c #243C74",
|
||||||
|
"C c #314070",
|
||||||
|
"D c #44568D",
|
||||||
|
"E c #5C72B4",
|
||||||
|
"F c #6F87CE",
|
||||||
|
"G c #7089D0",
|
||||||
|
"H c #728CD2",
|
||||||
|
"I c #748ED3",
|
||||||
|
"J c #7590D5",
|
||||||
|
"K c #7892D6",
|
||||||
|
"L c #7994D9",
|
||||||
|
"M c #7B97DB",
|
||||||
|
"N c #7E9ADE",
|
||||||
|
"O c #809DDF",
|
||||||
|
"P c #6EA1F7",
|
||||||
|
"Q c #699DF3",
|
||||||
|
"R c #4369C7",
|
||||||
|
"S c #406ACD",
|
||||||
|
"T c #416CD0",
|
||||||
|
"U c #416DD2",
|
||||||
|
"V c #416FD4",
|
||||||
|
"W c #4170D5",
|
||||||
|
"X c #3D69C9",
|
||||||
|
"Y c #1F3974",
|
||||||
|
"Z c #000000",
|
||||||
|
"` c #1D3A6B",
|
||||||
|
" . c #315CA3",
|
||||||
|
".. c #305BA3",
|
||||||
|
"+. c #1C3A6B",
|
||||||
|
"@. c #414E74",
|
||||||
|
"#. c #7D92CD",
|
||||||
|
"$. c #8099D8",
|
||||||
|
"%. c #829BDB",
|
||||||
|
"&. c #86A1DE",
|
||||||
|
"*. c #8AA6E2",
|
||||||
|
"=. c #8DA9E6",
|
||||||
|
"-. c #8FACE8",
|
||||||
|
";. c #91ADE9",
|
||||||
|
">. c #91AFEA",
|
||||||
|
",. c #95B2EC",
|
||||||
|
"'. c #6A9FF7",
|
||||||
|
"). c #6B9FF7",
|
||||||
|
"!. c #5B88E0",
|
||||||
|
"~. c #3D63C5",
|
||||||
|
"{. c #3F6ACE",
|
||||||
|
"]. c #406CD1",
|
||||||
|
"^. c #406ED3",
|
||||||
|
"/. c #3C68C7",
|
||||||
|
"(. c #11234C",
|
||||||
|
"_. c #203863",
|
||||||
|
":. c #457CD9",
|
||||||
|
"<. c #4E8DF5",
|
||||||
|
"[. c #4D8CF5",
|
||||||
|
"}. c #4C8CF5",
|
||||||
|
"|. c #427BD9",
|
||||||
|
"1. c #1F3863",
|
||||||
|
"2. c #2B354F",
|
||||||
|
"3. c #89A2DA",
|
||||||
|
"4. c #91ADE8",
|
||||||
|
"5. c #92AFEA",
|
||||||
|
"6. c #93B0EB",
|
||||||
|
"7. c #94B1EC",
|
||||||
|
"8. c #95B2ED",
|
||||||
|
"9. c #96B4ED",
|
||||||
|
"0. c #97B5EE",
|
||||||
|
"a. c #98B6EF",
|
||||||
|
"b. c #486FCC",
|
||||||
|
"c. c #3E65C7",
|
||||||
|
"d. c #3F6ACF",
|
||||||
|
"e. c #1F3872",
|
||||||
|
"f. c #4D8AF1",
|
||||||
|
"g. c #4C8BF5",
|
||||||
|
"h. c #4A88F1",
|
||||||
|
"i. c #1E3763",
|
||||||
|
"j. c #596888",
|
||||||
|
"k. c #96B3ED",
|
||||||
|
"l. c #98B5EF",
|
||||||
|
"m. c #99B7F0",
|
||||||
|
"n. c #9AB9F1",
|
||||||
|
"o. c #9BBAF2",
|
||||||
|
"p. c #9CBBF3",
|
||||||
|
"q. c #9DBCF5",
|
||||||
|
"r. c #699EF7",
|
||||||
|
"s. c #6393EB",
|
||||||
|
"t. c #3C63C5",
|
||||||
|
"u. c #3D65C9",
|
||||||
|
"v. c #365CB6",
|
||||||
|
"w. c #4B8BF5",
|
||||||
|
"x. c #407AD8",
|
||||||
|
"y. c #8DA6D7",
|
||||||
|
"z. c #9DBBF3",
|
||||||
|
"A. c #9EBCF4",
|
||||||
|
"B. c #9FBEF5",
|
||||||
|
"C. c #9FBFF6",
|
||||||
|
"D. c #A0C0F7",
|
||||||
|
"E. c #A1C1F8",
|
||||||
|
"F. c #A1C2F9",
|
||||||
|
"G. c #A2C3FA",
|
||||||
|
"H. c #4F7AD5",
|
||||||
|
"I. c #3C64C8",
|
||||||
|
"J. c #27438A",
|
||||||
|
"K. c #4A8AF4",
|
||||||
|
"L. c #498AF4",
|
||||||
|
"M. c #1B396A",
|
||||||
|
"N. c #778AB0",
|
||||||
|
"O. c #A2C1F8",
|
||||||
|
"P. c #A3C2F9",
|
||||||
|
"Q. c #A3C3F9",
|
||||||
|
"R. c #A3C3FA",
|
||||||
|
"S. c #689EF7",
|
||||||
|
"T. c #6599F1",
|
||||||
|
"U. c #3F66C8",
|
||||||
|
"V. c #23386F",
|
||||||
|
"W. c #2D59A2",
|
||||||
|
"X. c #75819B",
|
||||||
|
"Y. c #A4C4FA",
|
||||||
|
"Z. c #679DF7",
|
||||||
|
"`. c #5583DE",
|
||||||
|
" + c #24386F",
|
||||||
|
".+ c #4989F4",
|
||||||
|
"++ c #76829C",
|
||||||
|
"@+ c #A2C2FA",
|
||||||
|
"#+ c #679CF6",
|
||||||
|
"$+ c #669BF5",
|
||||||
|
"%+ c #335092",
|
||||||
|
"&+ c #1A386A",
|
||||||
|
"*+ c #7C8FB2",
|
||||||
|
"=+ c #A1C1F9",
|
||||||
|
"-+ c #669CF6",
|
||||||
|
";+ c #679DF6",
|
||||||
|
">+ c #5684D3",
|
||||||
|
",+ c #3F79D8",
|
||||||
|
"'+ c #97B1DF",
|
||||||
|
")+ c #A1C1FA",
|
||||||
|
"!+ c #3A588B",
|
||||||
|
"~+ c #4988F1",
|
||||||
|
"{+ c #4786F0",
|
||||||
|
"]+ c #1D3763",
|
||||||
|
"^+ c #64728E",
|
||||||
|
"/+ c #6194E9",
|
||||||
|
"(+ c #263B5E",
|
||||||
|
"_+ c #1D2D50",
|
||||||
|
":+ c #9FBAEC",
|
||||||
|
"<+ c #A1C2FA",
|
||||||
|
"[+ c #649AF4",
|
||||||
|
"}+ c #659BF6",
|
||||||
|
"|+ c #3B598B",
|
||||||
|
"1+ c #334D80",
|
||||||
|
"2+ c #83A2E1",
|
||||||
|
"3+ c #9FC0F8",
|
||||||
|
"4+ c #649BF6",
|
||||||
|
"5+ c #5B8BDA",
|
||||||
|
"6+ c #476CAB",
|
||||||
|
"7+ c #3C5888",
|
||||||
|
"8+ c #3F5A8A",
|
||||||
|
"9+ c #4A6AA8",
|
||||||
|
"0+ c #537ECE",
|
||||||
|
"a+ c #5F8CE5",
|
||||||
|
"b+ c #A2C0F7",
|
||||||
|
"c+ c #6399F4",
|
||||||
|
"d+ c #639AF6",
|
||||||
|
"e+ c #629AF6",
|
||||||
|
"f+ c #5E92EE",
|
||||||
|
"g+ c #5A8CE8",
|
||||||
|
"h+ c #8AACEE",
|
||||||
|
"i+ c #9EBFF7",
|
||||||
|
"j+ c #649AF5",
|
||||||
|
"k+ c #6299F6",
|
||||||
|
"l+ c #5B8FEB",
|
||||||
|
"m+ c #6994E8",
|
||||||
|
"n+ c #A0C1F9",
|
||||||
|
"o+ c #6399F5",
|
||||||
|
"p+ c #6096F3",
|
||||||
|
"q+ c #5B8DEA",
|
||||||
|
"r+ c #92B3F1",
|
||||||
|
"s+ c #6299F5",
|
||||||
|
"t+ c #6199F6",
|
||||||
|
"u+ c #5E94F1",
|
||||||
|
"v+ c #749CEB",
|
||||||
|
"w+ c #6198F5",
|
||||||
|
"x+ c #5B8FEC",
|
||||||
|
"y+ c #9BBCF6",
|
||||||
|
"z+ c #5F95F2",
|
||||||
|
"A+ c #5F96F2",
|
||||||
|
"B+ c #80A6EF",
|
||||||
|
"C+ c #9CBDF6",
|
||||||
|
"D+ c #6098F5",
|
||||||
|
"E+ c #6097F5",
|
||||||
|
"F+ c #6193EE",
|
||||||
|
"G+ c #9FC0F9",
|
||||||
|
"H+ c #9DBDF6",
|
||||||
|
"I+ c #5D93F1",
|
||||||
|
"J+ c #5B91EE",
|
||||||
|
"K+ c #82A6ED",
|
||||||
|
"L+ c #9DBDF5",
|
||||||
|
"M+ c #9CBCF5",
|
||||||
|
" ",
|
||||||
|
" . + @ + # $ ",
|
||||||
|
" % & * = = - ; > , ' - ) ",
|
||||||
|
" ! ~ { ] * * = - ; > , , ' ^ / ( ",
|
||||||
|
" _ : ~ { ] ] * = - ; > , , ' ^ / < [ ",
|
||||||
|
" } | 1 ~ { ] ] * = - ; > , , ' ^ / < 2 3 ",
|
||||||
|
" 4 5 6 7 8 { ] * * = - ; > , , ' ^ / < 2 9 0 ",
|
||||||
|
" a b c d e f { ] * = = - ; > , ' ' ^ / < 2 9 g h ",
|
||||||
|
" i j k b l m n o ] * = - - ; > , ' ^ ^ / < 2 9 g g [ ",
|
||||||
|
" p q r s t u v w x y z A B C D E F G H I J K L M N O ",
|
||||||
|
" P p Q R S T U V W X Y Z ` ...+.Z @.#.$.%.&.*.=.-.;.>.,. ",
|
||||||
|
" '.).).!.~.{.].^./.(._.:.<.[.[.}.|.1.2.3.4.5.6.7.8.9.0.a. ",
|
||||||
|
" '.'.'.).b.c.d.].e._.f.<.<.[.}.}.g.h.i.j.k.l.a.m.n.o.p.q. ",
|
||||||
|
" r.r.r.r.r.s.t.u.v.Z :.<.<.[.}.}.g.w.w.x.Z y.z.A.B.C.D.E.F.G. ",
|
||||||
|
" '.r.r.r.r.r.H.I.J.` <.<.[.}.}.g.g.w.K.L.M.N.O.P.Q.R.R.G.G.R. ",
|
||||||
|
" S.S.r.r.r.r.T.U.V. .[.[.}.}.g.g.w.K.K.L.W.X.Y.Y.R.R.R.G.G.G. ",
|
||||||
|
" Z.Z.S.S.S.S.S.`. +..[.}.}.g.g.w.K.K.L..+W.++Y.Y.R.R.G.G.G.@+ ",
|
||||||
|
" #+Z.Z.Z.Z.Z.Z.$+%++.}.g.g.g.w.K.K.L.L..+&+*+Y.R.R.R.G.G.@+=+ ",
|
||||||
|
" -+;+;+;+;+;+;+;+>+Z |.g.w.w.K.K.L.L..+,+Z '+R.R.R.G.G.G.@+)+ ",
|
||||||
|
" -+-+-+-+-+-+-+-+!+1.~+w.K.K.L.L..+{+]+^+Y.R.R.R.G.G.@+@+ ",
|
||||||
|
" -+-+-+-+-+-+-+-+/+(+1.x.L.L..+.+,+]+_+:+R.R.R.G.G.G.@+<+ ",
|
||||||
|
" [+}+-+-+-+}+}+}+}+/+|+Z M.W.W.&+Z 1+2+R.R.R.G.G.G.@+<+3+ ",
|
||||||
|
" }+}+}+}+}+4+4+4+4+}+5+6+7+8+9+0+a+b+R.R.G.G.G.@+@+<+ ",
|
||||||
|
" c+4+4+4+4+4+4+4+4+4+d+d+d+e+f+g+h+R.R.G.G.G.@+@+<+i+ ",
|
||||||
|
" j+4+4+4+4+4+d+d+d+d+e+e+k+l+m+P.R.G.G.G.@+@+<+n+ ",
|
||||||
|
" o+d+d+d+d+d+e+e+e+e+k+p+q+r+G.G.G.G.@+@+<+n+ ",
|
||||||
|
" s+e+e+e+e+e+k+k+k+t+u+v+R.G.G.G.@+@+<+n+ ",
|
||||||
|
" w+k+k+k+k+k+t+t+w+x+y+G.G.G.@+@+<+3+ ",
|
||||||
|
" z+t+t+t+t+t+t+A+B+G.G.@+@+<+<+C+ ",
|
||||||
|
" z+D+t+t+E+F+E.@+@+@+G+H+ ",
|
||||||
|
" I+J+K+L+H+M+ ",
|
||||||
|
" "};
|
BIN
chrome/app/theme/chromium/product_logo_128.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
chrome/app/theme/chromium/product_logo_24.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
chrome/app/theme/chromium/product_logo_256.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
chrome/app/theme/chromium/product_logo_48.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
chrome/app/theme/chromium/product_logo_64.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
chrome/app/theme/chromium/win/chromium.ico
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
chrome/app/theme/chromium/win/tiles/Logo.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
chrome/app/theme/chromium/win/tiles/SmallLogo.png
Normal file
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 7 KiB |
BIN
chrome/app/theme/default_100_percent/chromium/webstore_icon.png
Normal file
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 9.3 KiB |
BIN
chrome/app/theme/default_200_percent/chromium/webstore_icon.png
Normal file
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 6.8 KiB |
1042
chrome/browser/background/background_mode_manager.cc
Normal file
417
chrome/browser/net/stub_resolver_config_reader.cc
Normal file
|
@ -0,0 +1,417 @@
|
||||||
|
// Copyright 2020 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "chrome/browser/net/stub_resolver_config_reader.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "base/callback.h"
|
||||||
|
#include "base/check.h"
|
||||||
|
#include "base/feature_list.h"
|
||||||
|
#include "base/location.h"
|
||||||
|
#include "base/metrics/field_trial_params.h"
|
||||||
|
#include "base/metrics/histogram_macros.h"
|
||||||
|
#include "base/notreached.h"
|
||||||
|
#include "base/strings/string_piece.h"
|
||||||
|
#include "base/values.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
|
#include "build/chromeos_buildflags.h"
|
||||||
|
#include "chrome/browser/browser_process.h"
|
||||||
|
#include "chrome/browser/net/secure_dns_config.h"
|
||||||
|
#include "chrome/browser/net/secure_dns_util.h"
|
||||||
|
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
|
||||||
|
#include "chrome/common/chrome_features.h"
|
||||||
|
#include "chrome/common/pref_names.h"
|
||||||
|
#include "components/flags_ui/pref_service_flags_storage.h"
|
||||||
|
#include "components/prefs/pref_registry_simple.h"
|
||||||
|
#include "components/prefs/pref_service.h"
|
||||||
|
#include "content/public/browser/network_service_instance.h"
|
||||||
|
#include "net/dns/public/secure_dns_mode.h"
|
||||||
|
#include "net/dns/public/util.h"
|
||||||
|
#include "services/network/public/mojom/host_resolver.mojom.h"
|
||||||
|
#include "services/network/public/mojom/network_service.mojom.h"
|
||||||
|
|
||||||
|
#if defined(OS_ANDROID)
|
||||||
|
#include "base/android/build_info.h"
|
||||||
|
#include "chrome/browser/enterprise/util/android_enterprise_info.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
#include "base/enterprise_util.h"
|
||||||
|
#include "base/win/windows_version.h"
|
||||||
|
#include "chrome/browser/win/parental_controls.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Detailed descriptions of the secure DNS mode. These values are logged to UMA.
|
||||||
|
// Entries should not be renumbered and numeric values should never be reused.
|
||||||
|
// Please keep in sync with "SecureDnsModeDetails" in
|
||||||
|
// src/tools/metrics/histograms/enums.xml.
|
||||||
|
enum class SecureDnsModeDetailsForHistogram {
|
||||||
|
// The mode is controlled by the user and is set to 'off'.
|
||||||
|
kOffByUser = 0,
|
||||||
|
// The mode is controlled via enterprise policy and is set to 'off'.
|
||||||
|
kOffByEnterprisePolicy = 1,
|
||||||
|
// Chrome detected a managed environment and forced the mode to 'off'.
|
||||||
|
kOffByDetectedManagedEnvironment = 2,
|
||||||
|
// Chrome detected parental controls and forced the mode to 'off'.
|
||||||
|
kOffByDetectedParentalControls = 3,
|
||||||
|
// The mode is controlled by the user and is set to 'automatic' (the default
|
||||||
|
// mode).
|
||||||
|
kAutomaticByUser = 4,
|
||||||
|
// The mode is controlled via enterprise policy and is set to 'automatic'.
|
||||||
|
kAutomaticByEnterprisePolicy = 5,
|
||||||
|
// The mode is controlled by the user and is set to 'secure'.
|
||||||
|
kSecureByUser = 6,
|
||||||
|
// The mode is controlled via enterprise policy and is set to 'secure'.
|
||||||
|
kSecureByEnterprisePolicy = 7,
|
||||||
|
kMaxValue = kSecureByEnterprisePolicy,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
bool ShouldDisableDohForWindowsParentalControls() {
|
||||||
|
const WinParentalControls& parental_controls = GetWinParentalControls();
|
||||||
|
if (parental_controls.web_filter)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Some versions before Windows 8 may not fully support |web_filter|, so
|
||||||
|
// conservatively disable doh for any recognized parental controls.
|
||||||
|
if (parental_controls.any_restrictions &&
|
||||||
|
base::win::GetVersion() < base::win::Version::WIN8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // defined(OS_WIN)
|
||||||
|
|
||||||
|
// Check the AsyncDns field trial and return true if it should be enabled. On
|
||||||
|
// Android this includes checking the Android version in the field trial.
|
||||||
|
bool ShouldEnableAsyncDns() {
|
||||||
|
bool feature_can_be_enabled = true;
|
||||||
|
#if defined(OS_ANDROID)
|
||||||
|
int min_sdk =
|
||||||
|
base::GetFieldTrialParamByFeatureAsInt(features::kAsyncDns, "min_sdk", 0);
|
||||||
|
if (base::android::BuildInfo::GetInstance()->sdk_int() < min_sdk)
|
||||||
|
feature_can_be_enabled = false;
|
||||||
|
#endif
|
||||||
|
return feature_can_be_enabled &&
|
||||||
|
base::FeatureList::IsEnabled(features::kAsyncDns);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// static
|
||||||
|
constexpr base::TimeDelta StubResolverConfigReader::kParentalControlsCheckDelay;
|
||||||
|
|
||||||
|
StubResolverConfigReader::StubResolverConfigReader(PrefService* local_state,
|
||||||
|
bool set_up_pref_defaults)
|
||||||
|
: local_state_(local_state) {
|
||||||
|
base::RepeatingClosure pref_callback =
|
||||||
|
base::BindRepeating(&StubResolverConfigReader::UpdateNetworkService,
|
||||||
|
base::Unretained(this), false /* record_metrics */);
|
||||||
|
|
||||||
|
pref_change_registrar_.Init(local_state_);
|
||||||
|
|
||||||
|
// Update the DnsClient and DoH default preferences based on the corresponding
|
||||||
|
// features before registering change callbacks for these preferences.
|
||||||
|
// Changing prefs or defaults after registering change callbacks could result
|
||||||
|
// in reentrancy and mess up registration between this code and NetworkService
|
||||||
|
// creation.
|
||||||
|
if (set_up_pref_defaults) {
|
||||||
|
local_state_->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled,
|
||||||
|
base::Value(ShouldEnableAsyncDns()));
|
||||||
|
net::SecureDnsMode default_secure_dns_mode = net::SecureDnsMode::kOff;
|
||||||
|
std::string default_doh_templates;
|
||||||
|
if (base::FeatureList::IsEnabled(features::kDnsOverHttps)) {
|
||||||
|
if (features::kDnsOverHttpsFallbackParam.Get()) {
|
||||||
|
default_secure_dns_mode = net::SecureDnsMode::kAutomatic;
|
||||||
|
} else {
|
||||||
|
default_secure_dns_mode = net::SecureDnsMode::kSecure;
|
||||||
|
}
|
||||||
|
default_doh_templates = features::kDnsOverHttpsTemplatesParam.Get();
|
||||||
|
}
|
||||||
|
local_state_->SetDefaultPrefValue(
|
||||||
|
prefs::kDnsOverHttpsMode,
|
||||||
|
base::Value(SecureDnsConfig::ModeToString(default_secure_dns_mode)));
|
||||||
|
local_state_->SetDefaultPrefValue(prefs::kDnsOverHttpsTemplates,
|
||||||
|
base::Value(default_doh_templates));
|
||||||
|
|
||||||
|
// If the user has explicitly enabled or disabled the DoH experiment in
|
||||||
|
// chrome://flags and the DoH UI setting is not visible, store that choice
|
||||||
|
// in the user prefs so that it can be persisted after the experiment ends.
|
||||||
|
// Also make sure to remove the stored prefs value if the user has changed
|
||||||
|
// their chrome://flags selection to the default.
|
||||||
|
if (!features::kDnsOverHttpsShowUiParam.Get()) {
|
||||||
|
flags_ui::PrefServiceFlagsStorage flags_storage(local_state_);
|
||||||
|
std::set<std::string> entries = flags_storage.GetFlags();
|
||||||
|
if (entries.count("dns-over-https@1")) {
|
||||||
|
// The user has "Enabled" selected.
|
||||||
|
local_state_->SetString(prefs::kDnsOverHttpsMode,
|
||||||
|
SecureDnsConfig::kModeSecure);
|
||||||
|
} else if (entries.count("dns-over-https@2")) {
|
||||||
|
// The user has "Disabled" selected.
|
||||||
|
local_state_->SetString(prefs::kDnsOverHttpsMode,
|
||||||
|
SecureDnsConfig::kModeOff);
|
||||||
|
} else {
|
||||||
|
// The user has "Default" selected.
|
||||||
|
local_state_->ClearPref(prefs::kDnsOverHttpsMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pref_change_registrar_.Add(prefs::kBuiltInDnsClientEnabled, pref_callback);
|
||||||
|
pref_change_registrar_.Add(prefs::kDnsOverHttpsMode, pref_callback);
|
||||||
|
pref_change_registrar_.Add(prefs::kDnsOverHttpsTemplates, pref_callback);
|
||||||
|
pref_change_registrar_.Add(prefs::kAdditionalDnsQueryTypesEnabled,
|
||||||
|
pref_callback);
|
||||||
|
|
||||||
|
parental_controls_delay_timer_.Start(
|
||||||
|
FROM_HERE, kParentalControlsCheckDelay,
|
||||||
|
base::BindOnce(&StubResolverConfigReader::OnParentalControlsDelayTimer,
|
||||||
|
base::Unretained(this)));
|
||||||
|
|
||||||
|
#if defined(OS_ANDROID)
|
||||||
|
chrome::enterprise_util::AndroidEnterpriseInfo::GetInstance()
|
||||||
|
->GetAndroidEnterpriseInfoState(base::BindOnce(
|
||||||
|
&StubResolverConfigReader::OnAndroidOwnedStateCheckComplete,
|
||||||
|
weak_factory_.GetWeakPtr()));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
StubResolverConfigReader::~StubResolverConfigReader() = default;
|
||||||
|
|
||||||
|
// static
|
||||||
|
void StubResolverConfigReader::RegisterPrefs(PrefRegistrySimple* registry) {
|
||||||
|
// Register the DnsClient and DoH preferences. The feature list has not been
|
||||||
|
// initialized yet, so setting the preference defaults here to reflect the
|
||||||
|
// corresponding features will only cause the preference defaults to reflect
|
||||||
|
// the feature defaults (feature values set via the command line will not be
|
||||||
|
// captured). Thus, the preference defaults are updated in the constructor
|
||||||
|
// for SystemNetworkContextManager, at which point the feature list is ready.
|
||||||
|
registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, false);
|
||||||
|
registry->RegisterStringPref(prefs::kDnsOverHttpsMode, std::string());
|
||||||
|
registry->RegisterStringPref(prefs::kDnsOverHttpsTemplates, std::string());
|
||||||
|
registry->RegisterBooleanPref(prefs::kAdditionalDnsQueryTypesEnabled, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SecureDnsConfig StubResolverConfigReader::GetSecureDnsConfiguration(
|
||||||
|
bool force_check_parental_controls_for_automatic_mode) {
|
||||||
|
return GetAndUpdateConfiguration(
|
||||||
|
force_check_parental_controls_for_automatic_mode,
|
||||||
|
false /* record_metrics */, false /* update_network_service */);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StubResolverConfigReader::UpdateNetworkService(bool record_metrics) {
|
||||||
|
GetAndUpdateConfiguration(
|
||||||
|
false /* force_check_parental_controls_for_automatic_mode */,
|
||||||
|
record_metrics, true /* update_network_service */);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StubResolverConfigReader::ShouldDisableDohForManaged() {
|
||||||
|
// This function ignores cloud policies which are loaded on a per-profile basis.
|
||||||
|
#if defined(OS_ANDROID)
|
||||||
|
// Check for MDM/management/owner apps. android_has_owner_ is true if either a
|
||||||
|
// device or policy owner app is discovered by
|
||||||
|
// GetAndroidEnterpriseInfoState(). If android_has_owner_ is nullopt, take a
|
||||||
|
// value of false so that we don't disable DoH during the async check.
|
||||||
|
|
||||||
|
// Because Android policies can only be loaded with owner apps this is
|
||||||
|
// sufficient to check for the prescences of policies as well.
|
||||||
|
if (android_has_owner_.value_or(false))
|
||||||
|
return true;
|
||||||
|
#elif defined(OS_WIN)
|
||||||
|
if (base::IsMachineExternallyManaged())
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
|
||||||
|
if (g_browser_process->browser_policy_connector()->HasMachineLevelPolicies())
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StubResolverConfigReader::ShouldDisableDohForParentalControls() {
|
||||||
|
if (parental_controls_testing_override_.has_value())
|
||||||
|
return parental_controls_testing_override_.value();
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
return ShouldDisableDohForWindowsParentalControls();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void StubResolverConfigReader::OnParentalControlsDelayTimer() {
|
||||||
|
DCHECK(!parental_controls_delay_timer_.IsRunning());
|
||||||
|
|
||||||
|
// No need to act if parental controls were checked early.
|
||||||
|
if (parental_controls_checked_)
|
||||||
|
return;
|
||||||
|
parental_controls_checked_ = true;
|
||||||
|
|
||||||
|
// If parental controls are enabled, force a config change so secure DNS can
|
||||||
|
// be disabled.
|
||||||
|
if (ShouldDisableDohForParentalControls())
|
||||||
|
UpdateNetworkService(false /* record_metrics */);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StubResolverConfigReader::GetInsecureStubResolverEnabled() {
|
||||||
|
return local_state_->GetBoolean(prefs::kBuiltInDnsClientEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
SecureDnsConfig StubResolverConfigReader::GetAndUpdateConfiguration(
|
||||||
|
bool force_check_parental_controls_for_automatic_mode,
|
||||||
|
bool record_metrics,
|
||||||
|
bool update_network_service) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
|
||||||
|
net::SecureDnsMode secure_dns_mode;
|
||||||
|
SecureDnsModeDetailsForHistogram mode_details;
|
||||||
|
SecureDnsConfig::ManagementMode forced_management_mode =
|
||||||
|
SecureDnsConfig::ManagementMode::kNoOverride;
|
||||||
|
bool is_managed =
|
||||||
|
local_state_->FindPreference(prefs::kDnsOverHttpsMode)->IsManaged();
|
||||||
|
if (!is_managed && ShouldDisableDohForManaged()) {
|
||||||
|
secure_dns_mode = net::SecureDnsMode::kOff;
|
||||||
|
forced_management_mode = SecureDnsConfig::ManagementMode::kDisabledManaged;
|
||||||
|
} else {
|
||||||
|
secure_dns_mode = SecureDnsConfig::ParseMode(
|
||||||
|
local_state_->GetString(prefs::kDnsOverHttpsMode))
|
||||||
|
.value_or(net::SecureDnsMode::kOff);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_parental_controls = false;
|
||||||
|
if (secure_dns_mode == net::SecureDnsMode::kSecure) {
|
||||||
|
mode_details =
|
||||||
|
is_managed ? SecureDnsModeDetailsForHistogram::kSecureByEnterprisePolicy
|
||||||
|
: SecureDnsModeDetailsForHistogram::kSecureByUser;
|
||||||
|
|
||||||
|
// SECURE mode must always check for parental controls immediately (unless
|
||||||
|
// enabled through policy, which takes precedence over parental controls)
|
||||||
|
// because the mode allows sending DoH requests immediately.
|
||||||
|
check_parental_controls = !is_managed;
|
||||||
|
} else if (secure_dns_mode == net::SecureDnsMode::kAutomatic) {
|
||||||
|
mode_details =
|
||||||
|
is_managed
|
||||||
|
? SecureDnsModeDetailsForHistogram::kAutomaticByEnterprisePolicy
|
||||||
|
: SecureDnsModeDetailsForHistogram::kAutomaticByUser;
|
||||||
|
|
||||||
|
// To avoid impacting startup performance, AUTOMATIC mode should defer
|
||||||
|
// checking parental for a short period. This delay should have no practical
|
||||||
|
// effect on DoH queries because DoH enabling probes do not start until a
|
||||||
|
// longer period after startup.
|
||||||
|
bool allow_check_parental_controls =
|
||||||
|
force_check_parental_controls_for_automatic_mode ||
|
||||||
|
parental_controls_checked_;
|
||||||
|
check_parental_controls = !is_managed && allow_check_parental_controls;
|
||||||
|
} else {
|
||||||
|
switch (forced_management_mode) {
|
||||||
|
case SecureDnsConfig::ManagementMode::kNoOverride:
|
||||||
|
mode_details =
|
||||||
|
is_managed
|
||||||
|
? SecureDnsModeDetailsForHistogram::kOffByEnterprisePolicy
|
||||||
|
: SecureDnsModeDetailsForHistogram::kOffByUser;
|
||||||
|
break;
|
||||||
|
case SecureDnsConfig::ManagementMode::kDisabledManaged:
|
||||||
|
mode_details =
|
||||||
|
SecureDnsModeDetailsForHistogram::kOffByDetectedManagedEnvironment;
|
||||||
|
break;
|
||||||
|
case SecureDnsConfig::ManagementMode::kDisabledParentalControls:
|
||||||
|
NOTREACHED();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to check for parental controls if DoH is already disabled.
|
||||||
|
check_parental_controls = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check parental controls last because it can be expensive and should only be
|
||||||
|
// checked if necessary for the otherwise-determined mode.
|
||||||
|
if (check_parental_controls) {
|
||||||
|
if (ShouldDisableDohForParentalControls()) {
|
||||||
|
forced_management_mode =
|
||||||
|
SecureDnsConfig::ManagementMode::kDisabledParentalControls;
|
||||||
|
secure_dns_mode = net::SecureDnsMode::kOff;
|
||||||
|
mode_details =
|
||||||
|
SecureDnsModeDetailsForHistogram::kOffByDetectedParentalControls;
|
||||||
|
|
||||||
|
// If parental controls had not previously been checked, need to update
|
||||||
|
// network service.
|
||||||
|
if (!parental_controls_checked_)
|
||||||
|
update_network_service = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
parental_controls_checked_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool additional_dns_query_types_enabled =
|
||||||
|
local_state_->GetBoolean(prefs::kAdditionalDnsQueryTypesEnabled);
|
||||||
|
|
||||||
|
if (record_metrics) {
|
||||||
|
UMA_HISTOGRAM_ENUMERATION("Net.DNS.DnsConfig.SecureDnsMode", mode_details);
|
||||||
|
if (!additional_dns_query_types_enabled || ShouldDisableDohForManaged()) {
|
||||||
|
UMA_HISTOGRAM_BOOLEAN("Net.DNS.DnsConfig.AdditionalDnsQueryTypesEnabled",
|
||||||
|
additional_dns_query_types_enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string doh_templates =
|
||||||
|
local_state_->GetString(prefs::kDnsOverHttpsTemplates);
|
||||||
|
std::string server_method;
|
||||||
|
std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
|
||||||
|
absl::optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>
|
||||||
|
servers_mojo;
|
||||||
|
if (!doh_templates.empty() && secure_dns_mode != net::SecureDnsMode::kOff) {
|
||||||
|
for (base::StringPiece server_template :
|
||||||
|
chrome_browser_net::secure_dns::SplitGroup(doh_templates)) {
|
||||||
|
if (!net::dns_util::IsValidDohTemplate(server_template, &server_method)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool use_post = server_method == "POST";
|
||||||
|
dns_over_https_servers.emplace_back(std::string(server_template),
|
||||||
|
use_post);
|
||||||
|
|
||||||
|
if (!servers_mojo.has_value()) {
|
||||||
|
servers_mojo = absl::make_optional<
|
||||||
|
std::vector<network::mojom::DnsOverHttpsServerPtr>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
network::mojom::DnsOverHttpsServerPtr server_mojo =
|
||||||
|
network::mojom::DnsOverHttpsServer::New();
|
||||||
|
server_mojo->server_template = std::string(server_template);
|
||||||
|
server_mojo->use_post = use_post;
|
||||||
|
servers_mojo->emplace_back(std::move(server_mojo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_network_service) {
|
||||||
|
content::GetNetworkService()->ConfigureStubHostResolver(
|
||||||
|
GetInsecureStubResolverEnabled(), secure_dns_mode,
|
||||||
|
std::move(servers_mojo), additional_dns_query_types_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SecureDnsConfig(secure_dns_mode, std::move(dns_over_https_servers),
|
||||||
|
forced_management_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_ANDROID)
|
||||||
|
void StubResolverConfigReader::OnAndroidOwnedStateCheckComplete(
|
||||||
|
bool has_profile_owner,
|
||||||
|
bool has_device_owner) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
android_has_owner_ = has_profile_owner || has_device_owner;
|
||||||
|
// update the network service if the actual result is "true" to save time.
|
||||||
|
if (android_has_owner_.value())
|
||||||
|
UpdateNetworkService(false /* record_metrics */);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!-- Copyright 2017 The Chromium Authors -->
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component type="desktop">
|
||||||
|
<id>thorium-browser.desktop</id>
|
||||||
|
<update_contact>chromium-dev@chromium.org</update_contact>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>BSD-3-Clause and LGPL-2.1+ and Apache-2.0 and IJG and MIT and GPL-2.0+ and ISC and OpenSSL and (MPL-1.1 or GPL-2.0 or LGPL-2.0)</project_license>
|
||||||
|
<name>Thorium Web Browser</name>
|
||||||
|
<summary>The web browser from the Chromium project</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Chromium is an open-source browser project that aims to build a safer, faster,
|
||||||
|
and more stable way to experience the web.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We invite you to join our effort to build a powerful platform for developing a
|
||||||
|
new generation of web applications.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Chromium supports Vorbis, Theora, WebM and HTML5 audio and video standards, but
|
||||||
|
does not include the non-free AAC, H.264, MP3 or Adobe Flash code that is found
|
||||||
|
in Chrome.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
<url type="homepage">https://www.chromium.org/Home</url>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image>https://www.gstatic.com/chrome/appstream/chrome-2.png</image>
|
||||||
|
<caption/>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<translation/>
|
||||||
|
<developer_name>The Chromium and Thorium Authors</developer_name>
|
||||||
|
<url type="bugtracker">https://www.chromium.org/for-testers/bug-reporting-guidelines</url>
|
||||||
|
<url type="help">https://chromium.googlesource.com/chromium/src/+/main/docs/linux/debugging.md</url>
|
||||||
|
</component>
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
#
|
||||||
|
# This file provides common configuration information for building
|
||||||
|
# chromium-browser packages for various platforms.
|
||||||
|
|
||||||
|
# Base name of the package.
|
||||||
|
PACKAGE="thorium-browser"
|
||||||
|
|
||||||
|
# Base name of the snap package
|
||||||
|
SNAPNAME="thorium"
|
||||||
|
|
||||||
|
# Filename of the main executable (for generating launcher scripts, etc.)
|
||||||
|
PROGNAME=chrome
|
||||||
|
|
||||||
|
# Base directory for package installation.
|
||||||
|
INSTALLDIR=/opt/chromium.org/chromium
|
||||||
|
|
||||||
|
# Display string for desktop menu/icon.
|
||||||
|
MENUNAME="Thorium Web Browser"
|
||||||
|
|
||||||
|
# Brief package description.
|
||||||
|
SHORTDESC="The web browser from Chromium.org and The Thorium Authors"
|
||||||
|
|
||||||
|
# Detailed package description.
|
||||||
|
FULLDESC="Thorium is a browser that combines a minimal design with sophisticated technology to make the web faster, safer, and easier."
|
||||||
|
|
||||||
|
# Package maintainer information.
|
||||||
|
# TODO(mmoss) Setup a mailbox for this address
|
||||||
|
MAINTNAME="Thorium Linux Maintainers"
|
||||||
|
MAINTMAIL="alex313031@gmail.com"
|
||||||
|
PRODUCTURL="http://www.chromium.org/"
|
275
chrome/installer/linux/common/desktop.template
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Name=Thorium Web Browser
|
||||||
|
# Only KDE 4 seems to use GenericName, so we reuse the KDE strings.
|
||||||
|
# From Ubuntu's language-pack-kde-XX-base packages, version 9.04-20090413.
|
||||||
|
GenericName=Web Browser
|
||||||
|
GenericName[ar]=متصفح الشبكة
|
||||||
|
GenericName[bg]=Уеб браузър
|
||||||
|
GenericName[ca]=Navegador web
|
||||||
|
GenericName[cs]=WWW prohlížeč
|
||||||
|
GenericName[da]=Browser
|
||||||
|
GenericName[de]=Web-Browser
|
||||||
|
GenericName[el]=Περιηγητής ιστού
|
||||||
|
GenericName[en_GB]=Web Browser
|
||||||
|
GenericName[es]=Navegador web
|
||||||
|
GenericName[et]=Veebibrauser
|
||||||
|
GenericName[fi]=WWW-selain
|
||||||
|
GenericName[fr]=Navigateur Web
|
||||||
|
GenericName[gu]=વેબ બ્રાઉઝર
|
||||||
|
GenericName[he]=דפדפן אינטרנט
|
||||||
|
GenericName[hi]=वेब ब्राउज़र
|
||||||
|
GenericName[hu]=Webböngésző
|
||||||
|
GenericName[it]=Browser Web
|
||||||
|
GenericName[ja]=ウェブブラウザ
|
||||||
|
GenericName[kn]=ಜಾಲ ವೀಕ್ಷಕ
|
||||||
|
GenericName[ko]=웹 브라우저
|
||||||
|
GenericName[lt]=Žiniatinklio naršyklė
|
||||||
|
GenericName[lv]=Tīmekļa pārlūks
|
||||||
|
GenericName[ml]=വെബ് ബ്രൌസര്
|
||||||
|
GenericName[mr]=वेब ब्राऊजर
|
||||||
|
GenericName[nb]=Nettleser
|
||||||
|
GenericName[nl]=Webbrowser
|
||||||
|
GenericName[pl]=Przeglądarka WWW
|
||||||
|
GenericName[pt]=Navegador Web
|
||||||
|
GenericName[pt_BR]=Navegador da Internet
|
||||||
|
GenericName[ro]=Navigator de Internet
|
||||||
|
GenericName[ru]=Веб-браузер
|
||||||
|
GenericName[sl]=Spletni brskalnik
|
||||||
|
GenericName[sv]=Webbläsare
|
||||||
|
GenericName[ta]=இணைய உலாவி
|
||||||
|
GenericName[th]=เว็บเบราว์เซอร์
|
||||||
|
GenericName[tr]=Web Tarayıcı
|
||||||
|
GenericName[uk]=Навігатор Тенет
|
||||||
|
GenericName[zh_CN]=网页浏览器
|
||||||
|
GenericName[zh_HK]=網頁瀏覽器
|
||||||
|
GenericName[zh_TW]=網頁瀏覽器
|
||||||
|
# Not translated in KDE, from Epiphany 2.26.1-0ubuntu1.
|
||||||
|
GenericName[bn]=ওয়েব ব্রাউজার
|
||||||
|
GenericName[fil]=Web Browser
|
||||||
|
GenericName[hr]=Web preglednik
|
||||||
|
GenericName[id]=Browser Web
|
||||||
|
GenericName[or]=ଓ୍ବେବ ବ୍ରାଉଜର
|
||||||
|
GenericName[sk]=WWW prehliadač
|
||||||
|
GenericName[sr]=Интернет прегледник
|
||||||
|
GenericName[te]=మహాతల అన్వేషి
|
||||||
|
GenericName[vi]=Bộ duyệt Web
|
||||||
|
# Gnome and KDE 3 uses Comment.
|
||||||
|
Comment=Access the Internet
|
||||||
|
Comment[ar]=الدخول إلى الإنترنت
|
||||||
|
Comment[bg]=Достъп до интернет
|
||||||
|
Comment[bn]=ইন্টারনেটটি অ্যাক্সেস করুন
|
||||||
|
Comment[ca]=Accedeix a Internet
|
||||||
|
Comment[cs]=Přístup k internetu
|
||||||
|
Comment[da]=Få adgang til internettet
|
||||||
|
Comment[de]=Internetzugriff
|
||||||
|
Comment[el]=Πρόσβαση στο Διαδίκτυο
|
||||||
|
Comment[en_GB]=Access the Internet
|
||||||
|
Comment[es]=Accede a Internet.
|
||||||
|
Comment[et]=Pääs Internetti
|
||||||
|
Comment[fi]=Käytä internetiä
|
||||||
|
Comment[fil]=I-access ang Internet
|
||||||
|
Comment[fr]=Accéder à Internet
|
||||||
|
Comment[gu]=ઇંટરનેટ ઍક્સેસ કરો
|
||||||
|
Comment[he]=גישה אל האינטרנט
|
||||||
|
Comment[hi]=इंटरनेट तक पहुंच स्थापित करें
|
||||||
|
Comment[hr]=Pristup Internetu
|
||||||
|
Comment[hu]=Internetelérés
|
||||||
|
Comment[id]=Akses Internet
|
||||||
|
Comment[it]=Accesso a Internet
|
||||||
|
Comment[ja]=インターネットにアクセス
|
||||||
|
Comment[kn]=ಇಂಟರ್ನೆಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಿ
|
||||||
|
Comment[ko]=인터넷 연결
|
||||||
|
Comment[lt]=Interneto prieiga
|
||||||
|
Comment[lv]=Piekļūt internetam
|
||||||
|
Comment[ml]=ഇന്റര്നെറ്റ് ആക്സസ് ചെയ്യുക
|
||||||
|
Comment[mr]=इंटरनेटमध्ये प्रवेश करा
|
||||||
|
Comment[nb]=Gå til Internett
|
||||||
|
Comment[nl]=Verbinding maken met internet
|
||||||
|
Comment[or]=ଇଣ୍ଟର୍ନେଟ୍ ପ୍ରବେଶ କରନ୍ତୁ
|
||||||
|
Comment[pl]=Skorzystaj z internetu
|
||||||
|
Comment[pt]=Aceder à Internet
|
||||||
|
Comment[pt_BR]=Acessar a internet
|
||||||
|
Comment[ro]=Accesaţi Internetul
|
||||||
|
Comment[ru]=Доступ в Интернет
|
||||||
|
Comment[sk]=Prístup do siete Internet
|
||||||
|
Comment[sl]=Dostop do interneta
|
||||||
|
Comment[sr]=Приступите Интернету
|
||||||
|
Comment[sv]=Gå ut på Internet
|
||||||
|
Comment[ta]=இணையத்தை அணுகுதல்
|
||||||
|
Comment[te]=ఇంటర్నెట్ను ఆక్సెస్ చెయ్యండి
|
||||||
|
Comment[th]=เข้าถึงอินเทอร์เน็ต
|
||||||
|
Comment[tr]=İnternet'e erişin
|
||||||
|
Comment[uk]=Доступ до Інтернету
|
||||||
|
Comment[vi]=Truy cập Internet
|
||||||
|
Comment[zh_CN]=访问互联网
|
||||||
|
Comment[zh_HK]=連線到網際網路
|
||||||
|
Comment[zh_TW]=連線到網際網路
|
||||||
|
Exec=/opt/chromium.org/chromium-unstable/chrome --show-component-extension-options --autoplay-policy=user-gesture-required --enable-features=VaapiVideoDecoder %U
|
||||||
|
StartupNotify=true
|
||||||
|
Terminal=false
|
||||||
|
Icon=@@PACKAGE@@
|
||||||
|
Type=Application
|
||||||
|
Categories=Network;WebBrowser;
|
||||||
|
MimeType=application/pdf;application/rdf+xml;application/rss+xml;application/xhtml+xml;application/xhtml_xml;application/xml;image/gif;image/jpeg;image/png;image/webp;text/html;text/xml;x-scheme-handler/http;x-scheme-handler/https;
|
||||||
|
Actions=new-window;new-private-window;
|
||||||
|
|
||||||
|
[Desktop Action new-window]
|
||||||
|
Name=New Window
|
||||||
|
Name[am]=አዲስ መስኮት
|
||||||
|
Name[ar]=نافذة جديدة
|
||||||
|
Name[bg]=Нов прозорец
|
||||||
|
Name[bn]=নতুন উইন্ডো
|
||||||
|
Name[ca]=Finestra nova
|
||||||
|
Name[cs]=Nové okno
|
||||||
|
Name[da]=Nyt vindue
|
||||||
|
Name[de]=Neues Fenster
|
||||||
|
Name[el]=Νέο Παράθυρο
|
||||||
|
Name[en_GB]=New Window
|
||||||
|
Name[es]=Nueva ventana
|
||||||
|
Name[et]=Uus aken
|
||||||
|
Name[fa]=پنجره جدید
|
||||||
|
Name[fi]=Uusi ikkuna
|
||||||
|
Name[fil]=New Window
|
||||||
|
Name[fr]=Nouvelle fenêtre
|
||||||
|
Name[gu]=નવી વિંડો
|
||||||
|
Name[hi]=नई विंडो
|
||||||
|
Name[hr]=Novi prozor
|
||||||
|
Name[hu]=Új ablak
|
||||||
|
Name[id]=Jendela Baru
|
||||||
|
Name[it]=Nuova finestra
|
||||||
|
Name[iw]=חלון חדש
|
||||||
|
Name[ja]=新規ウインドウ
|
||||||
|
Name[kn]=ಹೊಸ ವಿಂಡೊ
|
||||||
|
Name[ko]=새 창
|
||||||
|
Name[lt]=Naujas langas
|
||||||
|
Name[lv]=Jauns logs
|
||||||
|
Name[ml]=പുതിയ വിന്ഡോ
|
||||||
|
Name[mr]=नवीन विंडो
|
||||||
|
Name[nl]=Nieuw venster
|
||||||
|
Name[no]=Nytt vindu
|
||||||
|
Name[pl]=Nowe okno
|
||||||
|
Name[pt]=Nova janela
|
||||||
|
Name[pt_BR]=Nova janela
|
||||||
|
Name[ro]=Fereastră nouă
|
||||||
|
Name[ru]=Новое окно
|
||||||
|
Name[sk]=Nové okno
|
||||||
|
Name[sl]=Novo okno
|
||||||
|
Name[sr]=Нови прозор
|
||||||
|
Name[sv]=Nytt fönster
|
||||||
|
Name[sw]=Dirisha Jipya
|
||||||
|
Name[ta]=புதிய சாளரம்
|
||||||
|
Name[te]=క్రొత్త విండో
|
||||||
|
Name[th]=หน้าต่างใหม่
|
||||||
|
Name[tr]=Yeni Pencere
|
||||||
|
Name[uk]=Нове вікно
|
||||||
|
Name[vi]=Cửa sổ Mới
|
||||||
|
Name[zh_CN]=新建窗口
|
||||||
|
Name[zh_TW]=開新視窗
|
||||||
|
Exec=/opt/chromium.org/chromium-unstable/chrome --show-component-extension-options --autoplay-policy=user-gesture-required --enable-features=VaapiVideoDecoder
|
||||||
|
|
||||||
|
[Desktop Action content-shell]
|
||||||
|
Name=Open Content Shell
|
||||||
|
Name[am]=አዲስ መስኮት
|
||||||
|
Name[ar]=نافذة جديدة
|
||||||
|
Name[bg]=Нов прозорец
|
||||||
|
Name[bn]=নতুন উইন্ডো
|
||||||
|
Name[ca]=Finestra nova
|
||||||
|
Name[cs]=Nové okno
|
||||||
|
Name[da]=Nyt vindue
|
||||||
|
Name[de]=Neues Fenster
|
||||||
|
Name[el]=Νέο Παράθυρο
|
||||||
|
Name[en_GB]=New Window
|
||||||
|
Name[es]=Nueva ventana
|
||||||
|
Name[et]=Uus aken
|
||||||
|
Name[fa]=پنجره جدید
|
||||||
|
Name[fi]=Uusi ikkuna
|
||||||
|
Name[fil]=New Window
|
||||||
|
Name[fr]=Nouvelle fenêtre
|
||||||
|
Name[gu]=નવી વિંડો
|
||||||
|
Name[hi]=नई विंडो
|
||||||
|
Name[hr]=Novi prozor
|
||||||
|
Name[hu]=Új ablak
|
||||||
|
Name[id]=Jendela Baru
|
||||||
|
Name[it]=Nuova finestra
|
||||||
|
Name[iw]=חלון חדש
|
||||||
|
Name[ja]=新規ウインドウ
|
||||||
|
Name[kn]=ಹೊಸ ವಿಂಡೊ
|
||||||
|
Name[ko]=새 창
|
||||||
|
Name[lt]=Naujas langas
|
||||||
|
Name[lv]=Jauns logs
|
||||||
|
Name[ml]=പുതിയ വിന്ഡോ
|
||||||
|
Name[mr]=नवीन विंडो
|
||||||
|
Name[nl]=Nieuw venster
|
||||||
|
Name[no]=Nytt vindu
|
||||||
|
Name[pl]=Nowe okno
|
||||||
|
Name[pt]=Nova janela
|
||||||
|
Name[pt_BR]=Nova janela
|
||||||
|
Name[ro]=Fereastră nouă
|
||||||
|
Name[ru]=Новое окно
|
||||||
|
Name[sk]=Nové okno
|
||||||
|
Name[sl]=Novo okno
|
||||||
|
Name[sr]=Нови прозор
|
||||||
|
Name[sv]=Nytt fönster
|
||||||
|
Name[sw]=Dirisha Jipya
|
||||||
|
Name[ta]=புதிய சாளரம்
|
||||||
|
Name[te]=క్రొత్త విండో
|
||||||
|
Name[th]=หน้าต่างใหม่
|
||||||
|
Name[tr]=Yeni Pencere
|
||||||
|
Name[uk]=Нове вікно
|
||||||
|
Name[vi]=Cửa sổ Mới
|
||||||
|
Name[zh_CN]=新建窗口
|
||||||
|
Name[zh_TW]=開新視窗
|
||||||
|
Exec=/opt/chromium.org/chromium-unstable/content_shell
|
||||||
|
|
||||||
|
[Desktop Action new-private-window]
|
||||||
|
Name=New Incognito Window
|
||||||
|
Name[ar]=نافذة جديدة للتصفح المتخفي
|
||||||
|
Name[bg]=Нов прозорец „инкогнито“
|
||||||
|
Name[bn]=নতুন ছদ্মবেশী উইন্ডো
|
||||||
|
Name[ca]=Finestra d'incògnit nova
|
||||||
|
Name[cs]=Nové anonymní okno
|
||||||
|
Name[da]=Nyt inkognitovindue
|
||||||
|
Name[de]=Neues Inkognito-Fenster
|
||||||
|
Name[el]=Νέο παράθυρο για ανώνυμη περιήγηση
|
||||||
|
Name[en_GB]=New Incognito window
|
||||||
|
Name[es]=Nueva ventana de incógnito
|
||||||
|
Name[et]=Uus inkognito aken
|
||||||
|
Name[fa]=پنجره جدید حالت ناشناس
|
||||||
|
Name[fi]=Uusi incognito-ikkuna
|
||||||
|
Name[fil]=Bagong Incognito window
|
||||||
|
Name[fr]=Nouvelle fenêtre de navigation privée
|
||||||
|
Name[gu]=નવી છુપી વિંડો
|
||||||
|
Name[hi]=नई गुप्त विंडो
|
||||||
|
Name[hr]=Novi anoniman prozor
|
||||||
|
Name[hu]=Új Inkognitóablak
|
||||||
|
Name[id]=Jendela Penyamaran baru
|
||||||
|
Name[it]=Nuova finestra di navigazione in incognito
|
||||||
|
Name[iw]=חלון חדש לגלישה בסתר
|
||||||
|
Name[ja]=新しいシークレット ウィンドウ
|
||||||
|
Name[kn]=ಹೊಸ ಅಜ್ಞಾತ ವಿಂಡೋ
|
||||||
|
Name[ko]=새 시크릿 창
|
||||||
|
Name[lt]=Naujas inkognito langas
|
||||||
|
Name[lv]=Jauns inkognito režīma logs
|
||||||
|
Name[ml]=പുതിയ വേഷ പ്രച്ഛന്ന വിന്ഡോ
|
||||||
|
Name[mr]=नवीन गुप्त विंडो
|
||||||
|
Name[nl]=Nieuw incognitovenster
|
||||||
|
Name[no]=Nytt inkognitovindu
|
||||||
|
Name[pl]=Nowe okno incognito
|
||||||
|
Name[pt]=Nova janela de navegação anónima
|
||||||
|
Name[pt_BR]=Nova janela anônima
|
||||||
|
Name[ro]=Fereastră nouă incognito
|
||||||
|
Name[ru]=Новое окно в режиме инкогнито
|
||||||
|
Name[sk]=Nové okno inkognito
|
||||||
|
Name[sl]=Novo okno brez beleženja zgodovine
|
||||||
|
Name[sr]=Нови прозор за прегледање без архивирања
|
||||||
|
Name[sv]=Nytt inkognitofönster
|
||||||
|
Name[ta]=புதிய மறைநிலைச் சாளரம்
|
||||||
|
Name[te]=క్రొత్త అజ్ఞాత విండో
|
||||||
|
Name[th]=หน้าต่างใหม่ที่ไม่ระบุตัวตน
|
||||||
|
Name[tr]=Yeni Gizli pencere
|
||||||
|
Name[uk]=Нове вікно в режимі анонімного перегляду
|
||||||
|
Name[vi]=Cửa sổ ẩn danh mới
|
||||||
|
Name[zh_CN]=新建隐身窗口
|
||||||
|
Name[zh_TW]=新增無痕式視窗
|
||||||
|
Exec=/opt/chromium.org/chromium-unstable/chrome --incognito --show-component-extension-options --autoplay-policy=user-gesture-required --enable-features=VaapiVideoDecoder
|
449
chrome/installer/linux/common/installer.include
Normal file
|
@ -0,0 +1,449 @@
|
||||||
|
# Shows the output of a given command only on failure, or when VERBOSE is set.
|
||||||
|
log_cmd() {
|
||||||
|
if [ "${VERBOSE:-}" ]; then
|
||||||
|
"$@"
|
||||||
|
else
|
||||||
|
# Record $- into a separate variable because it gets reset in the subshell.
|
||||||
|
FORWARD_SHELL_OPTS=$-
|
||||||
|
ERREXIT=$(echo ${FORWARD_SHELL_OPTS} | grep -o e || true)
|
||||||
|
set +${ERREXIT}
|
||||||
|
CMD_OUTPUT=$("$@" 2>&1)
|
||||||
|
ERRCODE=$?
|
||||||
|
set -${ERREXIT}
|
||||||
|
if [ ${ERRCODE} -ne 0 ]; then
|
||||||
|
echo "$@"
|
||||||
|
echo "${CMD_OUTPUT}"
|
||||||
|
if [ ${ERREXIT} ]; then
|
||||||
|
exit ${ERRCODE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Recursively replace @@include@@ template variables with the referenced file,
|
||||||
|
# and write the resulting text to stdout.
|
||||||
|
process_template_includes() {
|
||||||
|
INCSTACK+="$1->"
|
||||||
|
# Includes are relative to the file that does the include.
|
||||||
|
INCDIR=$(dirname $1)
|
||||||
|
# Clear IFS so 'read' doesn't trim whitespace
|
||||||
|
local OLDIFS="$IFS"
|
||||||
|
IFS=''
|
||||||
|
while read -r LINE
|
||||||
|
do
|
||||||
|
INCLINE=$(sed -e '/^[[:space:]]*@@include@@/!d' <<<$LINE)
|
||||||
|
if [ -n "$INCLINE" ]; then
|
||||||
|
INCFILE=$(echo $INCLINE | sed -e "s#@@include@@\(.*\)#\1#")
|
||||||
|
# Simple filename match to detect cyclic includes.
|
||||||
|
CYCLE=$(sed -e "\#$INCFILE#"'!d' <<<$INCSTACK)
|
||||||
|
if [ "$CYCLE" ]; then
|
||||||
|
echo "ERROR: Possible cyclic include detected." 1>&2
|
||||||
|
echo "$INCSTACK$INCFILE" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -r "$INCDIR/$INCFILE" ]; then
|
||||||
|
echo "ERROR: Couldn't read include file: $INCDIR/$INCFILE" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
process_template_includes "$INCDIR/$INCFILE"
|
||||||
|
else
|
||||||
|
echo "$LINE"
|
||||||
|
fi
|
||||||
|
done < "$1"
|
||||||
|
IFS="$OLDIFS"
|
||||||
|
INCSTACK=${INCSTACK%"$1->"}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Replace template variables (@@VARNAME@@) in the given template file. If a
|
||||||
|
# second argument is given, save the processed text to that filename, otherwise
|
||||||
|
# modify the template file in place.
|
||||||
|
process_template() (
|
||||||
|
# Don't worry if some of these substitution variables aren't set.
|
||||||
|
# Note that this function is run in a sub-shell so we don't leak this
|
||||||
|
# setting, since we still want unbound variables to be an error elsewhere.
|
||||||
|
set +u
|
||||||
|
|
||||||
|
local TMPLIN="$1"
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
local TMPLOUT="$TMPLIN"
|
||||||
|
else
|
||||||
|
local TMPLOUT="$2"
|
||||||
|
fi
|
||||||
|
# Process includes first so included text also gets substitutions.
|
||||||
|
TMPLINCL="$(process_template_includes "$TMPLIN")"
|
||||||
|
sed \
|
||||||
|
-e "s#@@PACKAGE@@#${PACKAGE}#g" \
|
||||||
|
-e "s#@@PACKAGE_ORIG@@#${PACKAGE_ORIG}#g" \
|
||||||
|
-e "s#@@PACKAGE_FILENAME@@#${PACKAGE_FILENAME}#g" \
|
||||||
|
-e "s#@@SNAPNAME@@#${SNAPNAME}#g" \
|
||||||
|
-e "s#@@PROGNAME@@#${PROGNAME}#g" \
|
||||||
|
-e "s#@@CHANNEL@@#${CHANNEL}#g" \
|
||||||
|
-e "s#@@COMPANY_FULLNAME@@#${COMPANY_FULLNAME}#g" \
|
||||||
|
-e "s#@@VERSION@@#${VERSION}#g" \
|
||||||
|
-e "s#@@PACKAGE_RELEASE@@#${PACKAGE_RELEASE}#g" \
|
||||||
|
-e "s#@@VERSIONFULL@@#${VERSIONFULL}#g" \
|
||||||
|
-e "s#@@INSTALLDIR@@#${INSTALLDIR}#g" \
|
||||||
|
-e "s#@@BUILDDIR@@#${OUTPUTDIR}#g" \
|
||||||
|
-e "s#@@STAGEDIR@@#${STAGEDIR}#g" \
|
||||||
|
-e "s#@@SCRIPTDIR@@#${SCRIPTDIR}#g" \
|
||||||
|
-e "s#@@MENUNAME@@#${MENUNAME}#g" \
|
||||||
|
-e "s#@@PRODUCTURL@@#${PRODUCTURL}#g" \
|
||||||
|
-e "s#@@PREDEPENDS@@#${PREDEPENDS}#g" \
|
||||||
|
-e "s#@@DEPENDS@@#${DEPENDS}#g" \
|
||||||
|
-e "s#@@RECOMMENDS@@#${RECOMMENDS}#g" \
|
||||||
|
-e "s#@@PROVIDES@@#${PROVIDES}#g" \
|
||||||
|
-e "s#@@ARCHITECTURE@@#${ARCHITECTURE}#g" \
|
||||||
|
-e "s#@@MAINTNAME@@#${MAINTNAME}#g" \
|
||||||
|
-e "s#@@MAINTMAIL@@#${MAINTMAIL}#g" \
|
||||||
|
-e "s#@@REPOCONFIG@@#${REPOCONFIG}#g" \
|
||||||
|
-e "s#@@REPOCONFIGREGEX@@#${REPOCONFIGREGEX}#g" \
|
||||||
|
-e "s#@@SHORTDESC@@#${SHORTDESC}#g" \
|
||||||
|
-e "s#@@FULLDESC@@#${FULLDESC}#g" \
|
||||||
|
-e "s#@@USR_BIN_SYMLINK_NAME@@#${USR_BIN_SYMLINK_NAME:-}#g" \
|
||||||
|
-e "s#@@LOGO_RESOURCES_PNG@@#${LOGO_RESOURCES_PNG}#g" \
|
||||||
|
-e "s#@@LOGO_RESOURCE_XPM@@#${LOGO_RESOURCE_XPM}#g" \
|
||||||
|
-e "s#@@DATE_RFC5322@@#$(date --rfc-email)#g" \
|
||||||
|
> "$TMPLOUT" <<< "$TMPLINCL"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Setup the installation directory hierarchy in the package staging area.
|
||||||
|
prep_staging_common() {
|
||||||
|
install -m 755 -d "${STAGEDIR}/${INSTALLDIR}" \
|
||||||
|
"${STAGEDIR}/usr/bin" \
|
||||||
|
"${STAGEDIR}/usr/share/applications" \
|
||||||
|
"${STAGEDIR}/usr/share/appdata" \
|
||||||
|
"${STAGEDIR}/usr/share/gnome-control-center/default-apps" \
|
||||||
|
"${STAGEDIR}/usr/share/man/man1"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_version_info() {
|
||||||
|
source "${OUTPUTDIR}/installer/version.txt"
|
||||||
|
VERSION="${MAJOR}.${MINOR}.${BUILD}.${PATCH}"
|
||||||
|
# TODO(phajdan.jr): Provide a mechanism to pass a different package
|
||||||
|
# release number if needed. The meaning of it is to bump it for
|
||||||
|
# packaging-only changes while the underlying software has the same version.
|
||||||
|
# This corresponds to the Release field in RPM spec files and debian_revision
|
||||||
|
# component of the Version field for DEB control file.
|
||||||
|
# Generally with Chrome's fast release cycle it'd be more hassle to try
|
||||||
|
# to bump this number between releases.
|
||||||
|
PACKAGE_RELEASE="1"
|
||||||
|
}
|
||||||
|
|
||||||
|
stage_install_common() {
|
||||||
|
log_cmd echo "Staging common install files in '${STAGEDIR}'..."
|
||||||
|
|
||||||
|
# Note: Changes here may also need to be applied to ChromeOS's
|
||||||
|
# chromite/lib/chrome_util.py.
|
||||||
|
|
||||||
|
# Note: This only supports static binaries and does not work when the GN
|
||||||
|
# is_component_build flag is true.
|
||||||
|
|
||||||
|
# app
|
||||||
|
STRIPPEDFILE="${OUTPUTDIR}/${PROGNAME}.stripped"
|
||||||
|
install -m 755 "${STRIPPEDFILE}" "${STAGEDIR}/${INSTALLDIR}/${PROGNAME}"
|
||||||
|
|
||||||
|
# crashpad
|
||||||
|
buildfile="${OUTPUTDIR}/chrome_crashpad_handler"
|
||||||
|
strippedfile="${buildfile}.stripped"
|
||||||
|
debugfile="${buildfile}.debug"
|
||||||
|
"${OUTPUTDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
|
||||||
|
install -m 755 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/chrome_crashpad_handler"
|
||||||
|
|
||||||
|
# resources
|
||||||
|
install -m 644 "${OUTPUTDIR}/resources.pak" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
# TODO(mmoss): This has broken a couple times on adding new .pak files. Maybe
|
||||||
|
# we should flag all installer files in FILES.cfg and get them from there, so
|
||||||
|
# there's only one place people need to keep track of such things (and in
|
||||||
|
# only the public repository).
|
||||||
|
if [ -r "${OUTPUTDIR}/chrome_100_percent.pak" ]; then
|
||||||
|
install -m 644 "${OUTPUTDIR}/chrome_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
install -m 644 "${OUTPUTDIR}/chrome_200_percent.pak" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
else
|
||||||
|
install -m 644 "${OUTPUTDIR}/theme_resources_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
install -m 644 "${OUTPUTDIR}/ui_resources_100_percent.pak" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ICU data file; Necessary when the GN icu_use_data_file flag is true.
|
||||||
|
install -m 644 "${OUTPUTDIR}/icudtl.dat" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
|
||||||
|
# V8 snapshot files; Necessary when the GN v8_use_external_startup_data flag
|
||||||
|
# is true.
|
||||||
|
# Use v8_context_snapshot.bin instead of snapshot_blob.bin if it is available.
|
||||||
|
# TODO(crbug.com/764576): Unship snapshot_blob.bin on ChromeOS and drop this branch
|
||||||
|
if [ -f "${OUTPUTDIR}/v8_context_snapshot.bin" ]; then
|
||||||
|
install -m 644 "${OUTPUTDIR}/v8_context_snapshot.bin" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
else
|
||||||
|
install -m 644 "${OUTPUTDIR}/snapshot_blob.bin" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# sandbox
|
||||||
|
# Rename sandbox binary with hyphen instead of underscore because that's what
|
||||||
|
# the code looks for. Originally, the SCons build system may have had a bug
|
||||||
|
# where it did not support hyphens, so this is stuck as is to avoid breaking
|
||||||
|
# anyone who expects the build artifact to have the underscore.
|
||||||
|
# the code looks for, but the build targets can't use hyphens (scons bug?)
|
||||||
|
buildfile="${OUTPUTDIR}/${PROGNAME}_sandbox"
|
||||||
|
strippedfile="${buildfile}.stripped"
|
||||||
|
debugfile="${buildfile}.debug"
|
||||||
|
"${OUTPUTDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
|
||||||
|
install -m 4755 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/chrome-sandbox"
|
||||||
|
|
||||||
|
# l10n paks
|
||||||
|
install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/locales/"
|
||||||
|
find "${OUTPUTDIR}/locales" -type f -name '*.pak' -exec \
|
||||||
|
cp -a '{}' "${STAGEDIR}/${INSTALLDIR}/locales/" \;
|
||||||
|
find "${STAGEDIR}/${INSTALLDIR}/locales" -type f -exec chmod 644 '{}' \;
|
||||||
|
|
||||||
|
# TODO(https://crbug.com/1077934): The below conditions check for the
|
||||||
|
# existence of files to determine if they should be copied to the staging
|
||||||
|
# directory. However, these may be stale if the build config no longer
|
||||||
|
# builds these files. The build config should be obtained from gn rather than
|
||||||
|
# guessed based on the presence of files.
|
||||||
|
|
||||||
|
# MEI Preload
|
||||||
|
if [ -f "${OUTPUTDIR}/MEIPreload/manifest.json" ]; then
|
||||||
|
install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/MEIPreload/"
|
||||||
|
install -m 644 "${OUTPUTDIR}/MEIPreload/manifest.json" "${STAGEDIR}/${INSTALLDIR}/MEIPreload/"
|
||||||
|
install -m 644 "${OUTPUTDIR}/MEIPreload/preloaded_data.pb" "${STAGEDIR}/${INSTALLDIR}/MEIPreload/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Widevine CDM.
|
||||||
|
if [ -d "${OUTPUTDIR}/WidevineCdm" ]; then
|
||||||
|
# No need to strip; libwidevinecdm.so starts out stripped.
|
||||||
|
cp -a "${OUTPUTDIR}/WidevineCdm" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
find "${STAGEDIR}/${INSTALLDIR}/WidevineCdm" -type d -exec chmod 755 '{}' \;
|
||||||
|
find "${STAGEDIR}/${INSTALLDIR}/WidevineCdm" -type f -exec chmod 644 '{}' \;
|
||||||
|
find "${STAGEDIR}/${INSTALLDIR}/WidevineCdm" -name libwidevinecdm.so \
|
||||||
|
-exec chmod ${SHLIB_PERMS} '{}' \;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ANGLE
|
||||||
|
if [ -f "${OUTPUTDIR}/libEGL.so" ]; then
|
||||||
|
for file in libEGL.so libGLESv2.so; do
|
||||||
|
buildfile="${OUTPUTDIR}/${file}"
|
||||||
|
strippedfile="${buildfile}.stripped"
|
||||||
|
debugfile="${buildfile}.debug"
|
||||||
|
"${OUTPUTDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
|
||||||
|
install -m ${SHLIB_PERMS} "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/${file}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ANGLE's libvulkan library
|
||||||
|
if [ -f "${OUTPUTDIR}/libvulkan.so.1" ]; then
|
||||||
|
file="libvulkan.so.1"
|
||||||
|
buildfile="${OUTPUTDIR}/${file}"
|
||||||
|
strippedfile="${buildfile}.stripped"
|
||||||
|
debugfile="${buildfile}.debug"
|
||||||
|
"${OUTPUTDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
|
||||||
|
install -m 755 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/${file}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SwiftShader ES
|
||||||
|
if [ -f "${OUTPUTDIR}/swiftshader/libEGL.so" ]; then
|
||||||
|
install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/swiftshader/"
|
||||||
|
for file in libEGL.so libGLESv2.so; do
|
||||||
|
buildfile="${OUTPUTDIR}/swiftshader/${file}"
|
||||||
|
strippedfile="${buildfile}.stripped"
|
||||||
|
debugfile="${buildfile}.debug"
|
||||||
|
"${OUTPUTDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
|
||||||
|
install -m ${SHLIB_PERMS} "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/swiftshader/${file}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# SwiftShader VK
|
||||||
|
if [ -f "${OUTPUTDIR}/libvk_swiftshader.so" ]; then
|
||||||
|
install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
file="libvk_swiftshader.so"
|
||||||
|
buildfile="${OUTPUTDIR}/${file}"
|
||||||
|
strippedfile="${buildfile}.stripped"
|
||||||
|
debugfile="${buildfile}.debug"
|
||||||
|
"${OUTPUTDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
|
||||||
|
install -m ${SHLIB_PERMS} "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/${file}"
|
||||||
|
# Install the ICD json file to point ANGLE to libvk_swiftshader.so
|
||||||
|
install -m 644 "${OUTPUTDIR}/vk_swiftshader_icd.json" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# libc++
|
||||||
|
if [ -f "${OUTPUTDIR}/lib/libc++.so" ]; then
|
||||||
|
install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/lib/"
|
||||||
|
install -m ${SHLIB_PERMS} -s "${OUTPUTDIR}/lib/libc++.so" "${STAGEDIR}/${INSTALLDIR}/lib/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# nacl_helper and nacl_helper_bootstrap
|
||||||
|
# Don't use "-s" (strip) because this runs binutils "strip", which
|
||||||
|
# mangles the special ELF program headers of nacl_helper_bootstrap.
|
||||||
|
# Explicitly use eu-strip instead, because it doesn't have that problem.
|
||||||
|
for file in nacl_helper nacl_helper_bootstrap; do
|
||||||
|
buildfile="${OUTPUTDIR}/${file}"
|
||||||
|
if [ -f "${buildfile}" ]; then
|
||||||
|
strippedfile="${buildfile}.stripped"
|
||||||
|
debugfile="${buildfile}.debug"
|
||||||
|
"${OUTPUTDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
|
||||||
|
install -m 755 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/${file}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# Don't use "-s" (strip) because this would use the Linux toolchain to
|
||||||
|
# strip the NaCl binary, which has the potential to break it. It
|
||||||
|
# certainly resets the OSABI and ABIVERSION fields to non-NaCl values,
|
||||||
|
# although the NaCl IRT loader doesn't care about these fields. In any
|
||||||
|
# case, the IRT binaries are already stripped by NaCl's build process.
|
||||||
|
for filename in ${OUTPUTDIR}/nacl_irt_*.nexe; do
|
||||||
|
# Re-check the filename in case globbing matched nothing.
|
||||||
|
if [ -f "$filename" ]; then
|
||||||
|
install -m 644 "$filename" "${STAGEDIR}/${INSTALLDIR}/`basename "$filename"`"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# default apps
|
||||||
|
if [ -d "${OUTPUTDIR}/default_apps" ]; then
|
||||||
|
cp -a "${OUTPUTDIR}/default_apps" "${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
find "${STAGEDIR}/${INSTALLDIR}/default_apps" -type d -exec chmod 755 '{}' \;
|
||||||
|
find "${STAGEDIR}/${INSTALLDIR}/default_apps" -type f -exec chmod 644 '{}' \;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# launcher script and symlink
|
||||||
|
process_template "${OUTPUTDIR}/installer/common/wrapper" \
|
||||||
|
"${STAGEDIR}/${INSTALLDIR}/${PACKAGE}"
|
||||||
|
chmod 755 "${STAGEDIR}/${INSTALLDIR}/${PACKAGE}"
|
||||||
|
if [ ! -z "${PACKAGE_ORIG}" ]; then
|
||||||
|
if [ ! -f "${STAGEDIR}/${INSTALLDIR}/${PACKAGE_ORIG}" ]; then
|
||||||
|
ln -sn "${INSTALLDIR}/${PACKAGE}" \
|
||||||
|
"${STAGEDIR}/${INSTALLDIR}/${PACKAGE_ORIG}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ ! -z "${USR_BIN_SYMLINK_NAME}" ]; then
|
||||||
|
ln -snf "${INSTALLDIR}/${PACKAGE}" \
|
||||||
|
"${STAGEDIR}/usr/bin/${USR_BIN_SYMLINK_NAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# app icons
|
||||||
|
local icon_regex=".*product_logo_[0-9]\+\."
|
||||||
|
if [ "$BRANDING" = "google_chrome" ]; then
|
||||||
|
if [ "$CHANNEL" = "beta" ]; then
|
||||||
|
icon_regex=".*product_logo_[0-9]\+_beta\."
|
||||||
|
elif [ "$CHANNEL" = "unstable" ]; then
|
||||||
|
icon_regex=".*product_logo_[0-9]\+_dev\."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
LOGO_RESOURCES_PNG=$(find "${OUTPUTDIR}/installer/theme/" \
|
||||||
|
-regextype sed -regex "${icon_regex}png" -printf "%f ")
|
||||||
|
LOGO_RESOURCE_XPM=$(find "${OUTPUTDIR}/installer/theme/" \
|
||||||
|
-regextype sed -regex "${icon_regex}xpm" -printf "%f")
|
||||||
|
for logo in ${LOGO_RESOURCES_PNG} ${LOGO_RESOURCE_XPM}; do
|
||||||
|
install -m 644 \
|
||||||
|
"${OUTPUTDIR}/installer/theme/${logo}" \
|
||||||
|
"${STAGEDIR}/${INSTALLDIR}/"
|
||||||
|
done
|
||||||
|
|
||||||
|
# desktop integration
|
||||||
|
install -m 755 "${OUTPUTDIR}/xdg-mime" "${STAGEDIR}${INSTALLDIR}/"
|
||||||
|
install -m 755 "${OUTPUTDIR}/xdg-settings" "${STAGEDIR}${INSTALLDIR}/"
|
||||||
|
|
||||||
|
if [ ${PACKAGE:0:6} = google ]; then
|
||||||
|
process_template "${OUTPUTDIR}/installer/common/google-chrome.appdata.xml.template" \
|
||||||
|
"${STAGEDIR}/usr/share/appdata/${PACKAGE}.appdata.xml"
|
||||||
|
chmod 644 "${STAGEDIR}/usr/share/appdata/${PACKAGE}.appdata.xml"
|
||||||
|
else
|
||||||
|
install -m 644 "${OUTPUTDIR}/installer/common/chromium-browser.appdata.xml" \
|
||||||
|
"${STAGEDIR}/usr/share/appdata/${PACKAGE}.appdata.xml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
process_template "${OUTPUTDIR}/installer/common/desktop.template" \
|
||||||
|
"${STAGEDIR}/usr/share/applications/${PACKAGE}.desktop"
|
||||||
|
chmod 644 "${STAGEDIR}/usr/share/applications/${PACKAGE}.desktop"
|
||||||
|
process_template "${OUTPUTDIR}/installer/common/default-app.template" \
|
||||||
|
"${STAGEDIR}/usr/share/gnome-control-center/default-apps/${PACKAGE}.xml"
|
||||||
|
chmod 644 "${STAGEDIR}/usr/share/gnome-control-center/default-apps/${PACKAGE}.xml"
|
||||||
|
process_template "${OUTPUTDIR}/installer/common/default-app-block.template" \
|
||||||
|
"${STAGEDIR}${INSTALLDIR}/default-app-block"
|
||||||
|
chmod 644 "${STAGEDIR}${INSTALLDIR}/default-app-block"
|
||||||
|
|
||||||
|
# documentation
|
||||||
|
process_template "${OUTPUTDIR}/installer/common/manpage.1.in" \
|
||||||
|
"${STAGEDIR}/usr/share/man/man1/${USR_BIN_SYMLINK_NAME}.1"
|
||||||
|
gzip -9n "${STAGEDIR}/usr/share/man/man1/${USR_BIN_SYMLINK_NAME}.1"
|
||||||
|
chmod 644 "${STAGEDIR}/usr/share/man/man1/${USR_BIN_SYMLINK_NAME}.1.gz"
|
||||||
|
# The stable channel allows launching the app without the "-stable"
|
||||||
|
# suffix like the other channels. Create a linked man page for the
|
||||||
|
# app-without-the-channel case.
|
||||||
|
if [ ! -f "${STAGEDIR}/usr/share/man/man1/${PACKAGE}.1.gz" ]; then
|
||||||
|
ln -s "${USR_BIN_SYMLINK_NAME}.1.gz" \
|
||||||
|
"${STAGEDIR}/usr/share/man/man1/${PACKAGE}.1.gz"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check to make sure all the ELF binaries are stripped.
|
||||||
|
UNSTRIPPED=$(find "${STAGEDIR}/${INSTALLDIR}/" -type f | xargs file |
|
||||||
|
grep ELF | grep -c "not stripped" || true)
|
||||||
|
if [ "${UNSTRIPPED}" != "0" ]; then
|
||||||
|
echo "ERROR: Found ${UNSTRIPPED} unstripped ELF files." 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check to make sure no ELF binaries set RPATH.
|
||||||
|
if [ "${TARGET_OS}" != "chromeos" ]; then
|
||||||
|
RPATH_BINS=
|
||||||
|
for elf in $(find "${STAGEDIR}/${INSTALLDIR}/" -type f | xargs file |
|
||||||
|
grep ELF | awk '{print $1;}' | sed 's/:$//'); do
|
||||||
|
if readelf -d ${elf} | grep "(RPATH)" >/dev/null; then
|
||||||
|
RPATH_BINS="${RPATH_BINS} $(basename ${elf})"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "${RPATH_BINS}" ]; then
|
||||||
|
echo "ERROR: Found binaries with RPATH set:${RPATH_BINS}" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure ELF binaries live in INSTALLDIR exclusively.
|
||||||
|
ELF_OUTSIDE_INSTALLDIR=$(find "${STAGEDIR}/" -not -path \
|
||||||
|
"${STAGEDIR}${INSTALLDIR}/*" -type f | xargs file -b |
|
||||||
|
grep -ce "^ELF" || true)
|
||||||
|
if [ "${ELF_OUTSIDE_INSTALLDIR}" -ne 0 ]; then
|
||||||
|
echo "ERROR: Found ${ELF_OUTSIDE_INSTALLDIR} ELF binaries" \
|
||||||
|
"outside of ${INSTALLDIR}" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify file permissions.
|
||||||
|
for file in $(find "${STAGEDIR}" -mindepth 1); do
|
||||||
|
local actual_perms=$(stat -c "%a" "${file}")
|
||||||
|
local file_type="$(file -b "${file}")"
|
||||||
|
local base_name=$(basename "${file}")
|
||||||
|
if [[ "${file_type}" = "directory"* ]]; then
|
||||||
|
local expected_perms=755
|
||||||
|
elif [[ "${file_type}" = *"symbolic link"* ]]; then
|
||||||
|
if [[ "$(readlink ${file})" = "/"* ]]; then
|
||||||
|
# Absolute symlink.
|
||||||
|
local expect_exists="${STAGEDIR}/$(readlink "${file}")"
|
||||||
|
else
|
||||||
|
# Relative symlink.
|
||||||
|
local expect_exists="$(dirname "${file}")/$(readlink "${file}")"
|
||||||
|
fi
|
||||||
|
if [ ! -f "${expect_exists}" ]; then
|
||||||
|
echo "Broken symlink: ${file}" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
local expected_perms=777
|
||||||
|
elif [ "${base_name}" = "chrome-sandbox" ]; then
|
||||||
|
local expected_perms=4755
|
||||||
|
elif [[ "${base_name}" = "nacl_irt_"*".nexe" ]]; then
|
||||||
|
local expected_perms=644
|
||||||
|
elif [[ "${file_type}" = *"shell script"* ]]; then
|
||||||
|
local expected_perms=755
|
||||||
|
elif [[ "${file_type}" = ELF* ]]; then
|
||||||
|
if [[ "${base_name}" = *".so" ]]; then
|
||||||
|
local expected_perms=${SHLIB_PERMS}
|
||||||
|
else
|
||||||
|
local expected_perms=755
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Regular data file.
|
||||||
|
local expected_perms=644
|
||||||
|
fi
|
||||||
|
if [ ${expected_perms} -ne ${actual_perms} ]; then
|
||||||
|
echo Expected permissions on ${base_name} to be \
|
||||||
|
${expected_perms}, but they were ${actual_perms} 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
6
chrome/installer/linux/debian/debian.menu
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
?package(@@USR_BIN_SYMLINK_NAME@@):needs="x11" \
|
||||||
|
section="Applications/Network/Web Browsing" \
|
||||||
|
hints="Web browsers" \
|
||||||
|
title="Thorium Browser" \
|
||||||
|
icon="@@INSTALLDIR@@/@@LOGO_RESOURCE_XPM@@" \
|
||||||
|
command="@@INSTALLDIR@@/@@PACKAGE@@"
|
21
chrome/installer/linux/debian/manual_recommends
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Copyright 2019 The Chromium Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
#
|
||||||
|
# Recommended dependencies not in the dpkg-shlibdeps output.
|
||||||
|
|
||||||
|
# u2f udev rules have moved from being installed by default by systemd on Debian
|
||||||
|
# systems to a separate package called libu2f-udev. Pull it in manually so that
|
||||||
|
# u2f keys will work. TODO(https://crbug.com/784010): Move this to "Depends"
|
||||||
|
# once support for Jessie, Stretch, Trusty, and Xenial are dropped.
|
||||||
|
libu2f-udev
|
||||||
|
|
||||||
|
# Try to use Vulkan when possible. libvulkan1 is not available on Ubuntu Trusty
|
||||||
|
# or Debian Jessie, so it is added to "Recommends" instead of "Depends".
|
||||||
|
# TODO(https://crbug.com/784010): Move this to "Depends" once support for
|
||||||
|
# Trusty and Jessie are dropped. Note that the dependency must still be manually
|
||||||
|
# added since the library is dlopen()'ed.
|
||||||
|
libvulkan1
|
||||||
|
|
||||||
|
#Add unrar for unrar support
|
||||||
|
unrar
|
147
content/gpu/BUILD.gn
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
# Copyright 2014 The Chromium Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
|
# found in the LICENSE file.
|
||||||
|
|
||||||
|
import("//build/config/chromeos/ui_mode.gni")
|
||||||
|
import("//build/config/ui.gni")
|
||||||
|
import("//gpu/vulkan/features.gni")
|
||||||
|
import("//media/media_options.gni")
|
||||||
|
import("//media/gpu/args.gni")
|
||||||
|
|
||||||
|
# See //content/BUILD.gn for how this works.
|
||||||
|
group("gpu") {
|
||||||
|
visibility = [ "//content/*" ] # This is an internal content API.
|
||||||
|
|
||||||
|
if (is_component_build) {
|
||||||
|
public_deps = [ "//content" ]
|
||||||
|
} else {
|
||||||
|
public_deps = [ ":gpu_sources" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_component_build) {
|
||||||
|
link_target_type = "source_set"
|
||||||
|
} else {
|
||||||
|
link_target_type = "static_library"
|
||||||
|
}
|
||||||
|
|
||||||
|
target(link_target_type, "gpu_sources") {
|
||||||
|
# This is an internal content API. Code outside of the content "component"
|
||||||
|
# (like content/test and content/shell) should depend on ":gpu" above.
|
||||||
|
visibility = [ "//content/*" ]
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
"browser_exposed_gpu_interfaces.cc",
|
||||||
|
"browser_exposed_gpu_interfaces.h",
|
||||||
|
"gpu_child_thread.cc",
|
||||||
|
"gpu_child_thread.h",
|
||||||
|
"gpu_child_thread_receiver_bindings.cc",
|
||||||
|
"gpu_main.cc",
|
||||||
|
"gpu_process.cc",
|
||||||
|
"gpu_process.h",
|
||||||
|
"gpu_service_factory.cc",
|
||||||
|
"gpu_service_factory.h",
|
||||||
|
"in_process_gpu_thread.cc",
|
||||||
|
"in_process_gpu_thread.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
configs += [ "//content:content_implementation" ]
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
"//base",
|
||||||
|
"//base/third_party/dynamic_annotations",
|
||||||
|
"//build:branding_buildflags",
|
||||||
|
"//build:chromeos_buildflags",
|
||||||
|
"//components/viz/service",
|
||||||
|
"//content:export",
|
||||||
|
"//content/child",
|
||||||
|
"//content/common",
|
||||||
|
"//content/common:mojo_bindings",
|
||||||
|
"//content/public/child:child_sources",
|
||||||
|
"//content/public/common:common_sources",
|
||||||
|
"//gpu:gpu",
|
||||||
|
"//gpu/ipc/common:command_buffer_traits",
|
||||||
|
"//gpu/ipc/service",
|
||||||
|
"//ipc",
|
||||||
|
"//media:media_buildflags",
|
||||||
|
"//media/gpu",
|
||||||
|
"//media/mojo:buildflags",
|
||||||
|
|
||||||
|
# TODO(jrummell): As //media/gpu/ipc/service is a source_set in a
|
||||||
|
# component build, determine if it should not be included here.
|
||||||
|
# http://crbug.com/702833.
|
||||||
|
"//components/viz/service/main",
|
||||||
|
"//media/gpu/ipc/service",
|
||||||
|
"//media/mojo/clients:clients",
|
||||||
|
"//sandbox/policy:chromecast_sandbox_allowlist_buildflags",
|
||||||
|
"//services/service_manager/public/cpp",
|
||||||
|
"//services/service_manager/public/mojom",
|
||||||
|
"//services/tracing/public/cpp",
|
||||||
|
"//services/viz/privileged/mojom",
|
||||||
|
"//skia",
|
||||||
|
"//third_party/angle:angle_gpu_info_util",
|
||||||
|
"//ui/gfx/ipc",
|
||||||
|
"//ui/gl",
|
||||||
|
"//ui/gl/init",
|
||||||
|
"//ui/latency/ipc",
|
||||||
|
]
|
||||||
|
|
||||||
|
if (!is_chromeos_ash || !is_chrome_branded) {
|
||||||
|
deps += [
|
||||||
|
"//services/shape_detection:lib",
|
||||||
|
"//services/shape_detection/public/mojom",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_linux || is_chromeos) {
|
||||||
|
sources += [
|
||||||
|
"gpu_sandbox_hook_linux.cc",
|
||||||
|
"gpu_sandbox_hook_linux.h",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_android) {
|
||||||
|
deps += [
|
||||||
|
"//components/tracing:graphics_provider",
|
||||||
|
"//media",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mojo_media_host == "gpu") {
|
||||||
|
deps += [ "//media/mojo/services" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_linux || is_chromeos || is_mac || is_win) {
|
||||||
|
deps += [ "//sandbox" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_mac) {
|
||||||
|
deps += [ "//components/metal_util" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_x11) {
|
||||||
|
deps += [
|
||||||
|
"//ui/events/platform/x11",
|
||||||
|
"//ui/gfx/linux:gpu_memory_buffer_support_x11",
|
||||||
|
"//ui/gfx/x",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_ozone) {
|
||||||
|
deps += [ "//ui/ozone" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable_vulkan) {
|
||||||
|
deps += [ "//gpu/vulkan" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use DRI on desktop Linux builds.
|
||||||
|
if (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux &&
|
||||||
|
(!is_chromecast || is_cast_desktop_build)) {
|
||||||
|
configs += [ "//build/config/linux/dri" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_linux && use_vaapi) {
|
||||||
|
public_configs = [ "//build/config/linux/libva" ]
|
||||||
|
}
|
||||||
|
}
|
BIN
logos/Logo.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
logos/SmallLogo.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
logos/chrome_app_icon_192.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
logos/chrome_app_icon_32.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
logos/chromium.ico
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
logos/other/product_logo_16.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
logos/other/product_logo_32.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
logos/other/product_logo_name_22.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
logos/other/product_logo_name_22_white.png
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
logos/other/webstore_icon.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
logos/other/webstore_icon_16.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
logos/other/webstore_icon_24.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
logos/other/webstore_icon_32.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
logos/other/x2/product_logo_16.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
logos/other/x2/product_logo_32.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
logos/other/x2/product_logo_name_22.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
logos/other/x2/product_logo_name_22_white.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
logos/other/x2/webstore_icon.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
logos/other/x2/webstore_icon_16.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
logos/other/x2/webstore_icon_24.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
logos/other/x2/webstore_icon_32.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
logos/product_logo_128.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
logos/product_logo_16.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
logos/product_logo_22_mono.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
logos/product_logo_24.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
logos/product_logo_256.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
logos/product_logo_32.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
297
logos/product_logo_32.xpm
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
/* XPM */
|
||||||
|
static char * product_logo_32_xpm[] = {
|
||||||
|
"32 32 262 2",
|
||||||
|
" c None",
|
||||||
|
". c #4E7ADB",
|
||||||
|
"+ c #4C78DB",
|
||||||
|
"@ c #4C79DB",
|
||||||
|
"# c #4A77DA",
|
||||||
|
"$ c #4B78DA",
|
||||||
|
"% c #4D7ADB",
|
||||||
|
"& c #4776DA",
|
||||||
|
"* c #4272D9",
|
||||||
|
"= c #4172D9",
|
||||||
|
"- c #4171D9",
|
||||||
|
"; c #4071D9",
|
||||||
|
"> c #3F70D8",
|
||||||
|
", c #3E6FD8",
|
||||||
|
"' c #3D6FD8",
|
||||||
|
") c #4775DA",
|
||||||
|
"! c #4F7BDC",
|
||||||
|
"~ c #4574DA",
|
||||||
|
"{ c #4474D9",
|
||||||
|
"] c #4373D9",
|
||||||
|
"^ c #3D6ED8",
|
||||||
|
"/ c #3C6ED8",
|
||||||
|
"( c #4675DA",
|
||||||
|
"_ c #4976D8",
|
||||||
|
": c #4575D9",
|
||||||
|
"< c #3B6DD8",
|
||||||
|
"[ c #3F6FD8",
|
||||||
|
"} c #4773D5",
|
||||||
|
"| c #4573D6",
|
||||||
|
"1 c #4574D8",
|
||||||
|
"2 c #3A6CD7",
|
||||||
|
"3 c #3C6DD7",
|
||||||
|
"4 c #4670D2",
|
||||||
|
"5 c #4471D4",
|
||||||
|
"6 c #4472D5",
|
||||||
|
"7 c #4473D7",
|
||||||
|
"8 c #4573D9",
|
||||||
|
"9 c #396CD7",
|
||||||
|
"0 c #3B6DD7",
|
||||||
|
"a c #456ECF",
|
||||||
|
"b c #436ED1",
|
||||||
|
"c c #446FD2",
|
||||||
|
"d c #4470D4",
|
||||||
|
"e c #4471D6",
|
||||||
|
"f c #4472D8",
|
||||||
|
"g c #396BD7",
|
||||||
|
"h c #3B6CD7",
|
||||||
|
"i c #6C9AEE",
|
||||||
|
"j c #4169CB",
|
||||||
|
"k c #426DCF",
|
||||||
|
"l c #436FD3",
|
||||||
|
"m c #4370D5",
|
||||||
|
"n c #4372D7",
|
||||||
|
"o c #4372D8",
|
||||||
|
"p c #6BA0F7",
|
||||||
|
"q c #5580D9",
|
||||||
|
"r c #416ACD",
|
||||||
|
"s c #426CCF",
|
||||||
|
"t c #426ED1",
|
||||||
|
"u c #426FD3",
|
||||||
|
"v c #4270D5",
|
||||||
|
"w c #4271D7",
|
||||||
|
"x c #4272D8",
|
||||||
|
"y c #4172D8",
|
||||||
|
"z c #3861BC",
|
||||||
|
"A c #294992",
|
||||||
|
"B c #243C74",
|
||||||
|
"C c #314070",
|
||||||
|
"D c #44568D",
|
||||||
|
"E c #5C72B4",
|
||||||
|
"F c #6F87CE",
|
||||||
|
"G c #7089D0",
|
||||||
|
"H c #728CD2",
|
||||||
|
"I c #748ED3",
|
||||||
|
"J c #7590D5",
|
||||||
|
"K c #7892D6",
|
||||||
|
"L c #7994D9",
|
||||||
|
"M c #7B97DB",
|
||||||
|
"N c #7E9ADE",
|
||||||
|
"O c #809DDF",
|
||||||
|
"P c #6EA1F7",
|
||||||
|
"Q c #699DF3",
|
||||||
|
"R c #4369C7",
|
||||||
|
"S c #406ACD",
|
||||||
|
"T c #416CD0",
|
||||||
|
"U c #416DD2",
|
||||||
|
"V c #416FD4",
|
||||||
|
"W c #4170D5",
|
||||||
|
"X c #3D69C9",
|
||||||
|
"Y c #1F3974",
|
||||||
|
"Z c #000000",
|
||||||
|
"` c #1D3A6B",
|
||||||
|
" . c #315CA3",
|
||||||
|
".. c #305BA3",
|
||||||
|
"+. c #1C3A6B",
|
||||||
|
"@. c #414E74",
|
||||||
|
"#. c #7D92CD",
|
||||||
|
"$. c #8099D8",
|
||||||
|
"%. c #829BDB",
|
||||||
|
"&. c #86A1DE",
|
||||||
|
"*. c #8AA6E2",
|
||||||
|
"=. c #8DA9E6",
|
||||||
|
"-. c #8FACE8",
|
||||||
|
";. c #91ADE9",
|
||||||
|
">. c #91AFEA",
|
||||||
|
",. c #95B2EC",
|
||||||
|
"'. c #6A9FF7",
|
||||||
|
"). c #6B9FF7",
|
||||||
|
"!. c #5B88E0",
|
||||||
|
"~. c #3D63C5",
|
||||||
|
"{. c #3F6ACE",
|
||||||
|
"]. c #406CD1",
|
||||||
|
"^. c #406ED3",
|
||||||
|
"/. c #3C68C7",
|
||||||
|
"(. c #11234C",
|
||||||
|
"_. c #203863",
|
||||||
|
":. c #457CD9",
|
||||||
|
"<. c #4E8DF5",
|
||||||
|
"[. c #4D8CF5",
|
||||||
|
"}. c #4C8CF5",
|
||||||
|
"|. c #427BD9",
|
||||||
|
"1. c #1F3863",
|
||||||
|
"2. c #2B354F",
|
||||||
|
"3. c #89A2DA",
|
||||||
|
"4. c #91ADE8",
|
||||||
|
"5. c #92AFEA",
|
||||||
|
"6. c #93B0EB",
|
||||||
|
"7. c #94B1EC",
|
||||||
|
"8. c #95B2ED",
|
||||||
|
"9. c #96B4ED",
|
||||||
|
"0. c #97B5EE",
|
||||||
|
"a. c #98B6EF",
|
||||||
|
"b. c #486FCC",
|
||||||
|
"c. c #3E65C7",
|
||||||
|
"d. c #3F6ACF",
|
||||||
|
"e. c #1F3872",
|
||||||
|
"f. c #4D8AF1",
|
||||||
|
"g. c #4C8BF5",
|
||||||
|
"h. c #4A88F1",
|
||||||
|
"i. c #1E3763",
|
||||||
|
"j. c #596888",
|
||||||
|
"k. c #96B3ED",
|
||||||
|
"l. c #98B5EF",
|
||||||
|
"m. c #99B7F0",
|
||||||
|
"n. c #9AB9F1",
|
||||||
|
"o. c #9BBAF2",
|
||||||
|
"p. c #9CBBF3",
|
||||||
|
"q. c #9DBCF5",
|
||||||
|
"r. c #699EF7",
|
||||||
|
"s. c #6393EB",
|
||||||
|
"t. c #3C63C5",
|
||||||
|
"u. c #3D65C9",
|
||||||
|
"v. c #365CB6",
|
||||||
|
"w. c #4B8BF5",
|
||||||
|
"x. c #407AD8",
|
||||||
|
"y. c #8DA6D7",
|
||||||
|
"z. c #9DBBF3",
|
||||||
|
"A. c #9EBCF4",
|
||||||
|
"B. c #9FBEF5",
|
||||||
|
"C. c #9FBFF6",
|
||||||
|
"D. c #A0C0F7",
|
||||||
|
"E. c #A1C1F8",
|
||||||
|
"F. c #A1C2F9",
|
||||||
|
"G. c #A2C3FA",
|
||||||
|
"H. c #4F7AD5",
|
||||||
|
"I. c #3C64C8",
|
||||||
|
"J. c #27438A",
|
||||||
|
"K. c #4A8AF4",
|
||||||
|
"L. c #498AF4",
|
||||||
|
"M. c #1B396A",
|
||||||
|
"N. c #778AB0",
|
||||||
|
"O. c #A2C1F8",
|
||||||
|
"P. c #A3C2F9",
|
||||||
|
"Q. c #A3C3F9",
|
||||||
|
"R. c #A3C3FA",
|
||||||
|
"S. c #689EF7",
|
||||||
|
"T. c #6599F1",
|
||||||
|
"U. c #3F66C8",
|
||||||
|
"V. c #23386F",
|
||||||
|
"W. c #2D59A2",
|
||||||
|
"X. c #75819B",
|
||||||
|
"Y. c #A4C4FA",
|
||||||
|
"Z. c #679DF7",
|
||||||
|
"`. c #5583DE",
|
||||||
|
" + c #24386F",
|
||||||
|
".+ c #4989F4",
|
||||||
|
"++ c #76829C",
|
||||||
|
"@+ c #A2C2FA",
|
||||||
|
"#+ c #679CF6",
|
||||||
|
"$+ c #669BF5",
|
||||||
|
"%+ c #335092",
|
||||||
|
"&+ c #1A386A",
|
||||||
|
"*+ c #7C8FB2",
|
||||||
|
"=+ c #A1C1F9",
|
||||||
|
"-+ c #669CF6",
|
||||||
|
";+ c #679DF6",
|
||||||
|
">+ c #5684D3",
|
||||||
|
",+ c #3F79D8",
|
||||||
|
"'+ c #97B1DF",
|
||||||
|
")+ c #A1C1FA",
|
||||||
|
"!+ c #3A588B",
|
||||||
|
"~+ c #4988F1",
|
||||||
|
"{+ c #4786F0",
|
||||||
|
"]+ c #1D3763",
|
||||||
|
"^+ c #64728E",
|
||||||
|
"/+ c #6194E9",
|
||||||
|
"(+ c #263B5E",
|
||||||
|
"_+ c #1D2D50",
|
||||||
|
":+ c #9FBAEC",
|
||||||
|
"<+ c #A1C2FA",
|
||||||
|
"[+ c #649AF4",
|
||||||
|
"}+ c #659BF6",
|
||||||
|
"|+ c #3B598B",
|
||||||
|
"1+ c #334D80",
|
||||||
|
"2+ c #83A2E1",
|
||||||
|
"3+ c #9FC0F8",
|
||||||
|
"4+ c #649BF6",
|
||||||
|
"5+ c #5B8BDA",
|
||||||
|
"6+ c #476CAB",
|
||||||
|
"7+ c #3C5888",
|
||||||
|
"8+ c #3F5A8A",
|
||||||
|
"9+ c #4A6AA8",
|
||||||
|
"0+ c #537ECE",
|
||||||
|
"a+ c #5F8CE5",
|
||||||
|
"b+ c #A2C0F7",
|
||||||
|
"c+ c #6399F4",
|
||||||
|
"d+ c #639AF6",
|
||||||
|
"e+ c #629AF6",
|
||||||
|
"f+ c #5E92EE",
|
||||||
|
"g+ c #5A8CE8",
|
||||||
|
"h+ c #8AACEE",
|
||||||
|
"i+ c #9EBFF7",
|
||||||
|
"j+ c #649AF5",
|
||||||
|
"k+ c #6299F6",
|
||||||
|
"l+ c #5B8FEB",
|
||||||
|
"m+ c #6994E8",
|
||||||
|
"n+ c #A0C1F9",
|
||||||
|
"o+ c #6399F5",
|
||||||
|
"p+ c #6096F3",
|
||||||
|
"q+ c #5B8DEA",
|
||||||
|
"r+ c #92B3F1",
|
||||||
|
"s+ c #6299F5",
|
||||||
|
"t+ c #6199F6",
|
||||||
|
"u+ c #5E94F1",
|
||||||
|
"v+ c #749CEB",
|
||||||
|
"w+ c #6198F5",
|
||||||
|
"x+ c #5B8FEC",
|
||||||
|
"y+ c #9BBCF6",
|
||||||
|
"z+ c #5F95F2",
|
||||||
|
"A+ c #5F96F2",
|
||||||
|
"B+ c #80A6EF",
|
||||||
|
"C+ c #9CBDF6",
|
||||||
|
"D+ c #6098F5",
|
||||||
|
"E+ c #6097F5",
|
||||||
|
"F+ c #6193EE",
|
||||||
|
"G+ c #9FC0F9",
|
||||||
|
"H+ c #9DBDF6",
|
||||||
|
"I+ c #5D93F1",
|
||||||
|
"J+ c #5B91EE",
|
||||||
|
"K+ c #82A6ED",
|
||||||
|
"L+ c #9DBDF5",
|
||||||
|
"M+ c #9CBCF5",
|
||||||
|
" ",
|
||||||
|
" . + @ + # $ ",
|
||||||
|
" % & * = = - ; > , ' - ) ",
|
||||||
|
" ! ~ { ] * * = - ; > , , ' ^ / ( ",
|
||||||
|
" _ : ~ { ] ] * = - ; > , , ' ^ / < [ ",
|
||||||
|
" } | 1 ~ { ] ] * = - ; > , , ' ^ / < 2 3 ",
|
||||||
|
" 4 5 6 7 8 { ] * * = - ; > , , ' ^ / < 2 9 0 ",
|
||||||
|
" a b c d e f { ] * = = - ; > , ' ' ^ / < 2 9 g h ",
|
||||||
|
" i j k b l m n o ] * = - - ; > , ' ^ ^ / < 2 9 g g [ ",
|
||||||
|
" p q r s t u v w x y z A B C D E F G H I J K L M N O ",
|
||||||
|
" P p Q R S T U V W X Y Z ` ...+.Z @.#.$.%.&.*.=.-.;.>.,. ",
|
||||||
|
" '.).).!.~.{.].^./.(._.:.<.[.[.}.|.1.2.3.4.5.6.7.8.9.0.a. ",
|
||||||
|
" '.'.'.).b.c.d.].e._.f.<.<.[.}.}.g.h.i.j.k.l.a.m.n.o.p.q. ",
|
||||||
|
" r.r.r.r.r.s.t.u.v.Z :.<.<.[.}.}.g.w.w.x.Z y.z.A.B.C.D.E.F.G. ",
|
||||||
|
" '.r.r.r.r.r.H.I.J.` <.<.[.}.}.g.g.w.K.L.M.N.O.P.Q.R.R.G.G.R. ",
|
||||||
|
" S.S.r.r.r.r.T.U.V. .[.[.}.}.g.g.w.K.K.L.W.X.Y.Y.R.R.R.G.G.G. ",
|
||||||
|
" Z.Z.S.S.S.S.S.`. +..[.}.}.g.g.w.K.K.L..+W.++Y.Y.R.R.G.G.G.@+ ",
|
||||||
|
" #+Z.Z.Z.Z.Z.Z.$+%++.}.g.g.g.w.K.K.L.L..+&+*+Y.R.R.R.G.G.@+=+ ",
|
||||||
|
" -+;+;+;+;+;+;+;+>+Z |.g.w.w.K.K.L.L..+,+Z '+R.R.R.G.G.G.@+)+ ",
|
||||||
|
" -+-+-+-+-+-+-+-+!+1.~+w.K.K.L.L..+{+]+^+Y.R.R.R.G.G.@+@+ ",
|
||||||
|
" -+-+-+-+-+-+-+-+/+(+1.x.L.L..+.+,+]+_+:+R.R.R.G.G.G.@+<+ ",
|
||||||
|
" [+}+-+-+-+}+}+}+}+/+|+Z M.W.W.&+Z 1+2+R.R.R.G.G.G.@+<+3+ ",
|
||||||
|
" }+}+}+}+}+4+4+4+4+}+5+6+7+8+9+0+a+b+R.R.G.G.G.@+@+<+ ",
|
||||||
|
" c+4+4+4+4+4+4+4+4+4+d+d+d+e+f+g+h+R.R.G.G.G.@+@+<+i+ ",
|
||||||
|
" j+4+4+4+4+4+d+d+d+d+e+e+k+l+m+P.R.G.G.G.@+@+<+n+ ",
|
||||||
|
" o+d+d+d+d+d+e+e+e+e+k+p+q+r+G.G.G.G.@+@+<+n+ ",
|
||||||
|
" s+e+e+e+e+e+k+k+k+t+u+v+R.G.G.G.@+@+<+n+ ",
|
||||||
|
" w+k+k+k+k+k+t+t+w+x+y+G.G.G.@+@+<+3+ ",
|
||||||
|
" z+t+t+t+t+t+t+A+B+G.G.@+@+<+<+C+ ",
|
||||||
|
" z+D+t+t+E+F+E.@+@+@+G+H+ ",
|
||||||
|
" I+J+K+L+H+M+ ",
|
||||||
|
" "};
|
BIN
logos/product_logo_48.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
logos/product_logo_512.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
logos/product_logo_64.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
logos/technetium.png
Normal file
After Width: | Height: | Size: 359 B |
44
logos/technetium.svg
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="8192.000000pt" height="8192.000000pt" viewBox="0 0 8192.000000 8192.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
|
||||||
|
<g transform="translate(0.000000,8192.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M39940 78460 c-2828 -82 -5542 -453 -8215 -1121 -3543 -886 -6956
|
||||||
|
-2292 -10102 -4160 -3281 -1948 -6204 -4339 -8804 -7199 -1226 -1349 -2350
|
||||||
|
-2790 -3444 -4415 -93 -137 -170 -252 -172 -254 -2 -3 -35 26 -74 65 l-70 69
|
||||||
|
62 -110 c113 -201 1813 -3118 8669 -14875 1021 -1752 3226 -5534 4900 -8405
|
||||||
|
1673 -2871 3047 -5224 3053 -5230 5 -5 -4 15 -20 45 -139 252 -373 734 -537
|
||||||
|
1103 -1184 2668 -1665 5588 -1406 8532 213 2410 937 4757 2118 6865 1350 2410
|
||||||
|
3256 4462 5557 5985 2674 1769 5729 2738 8965 2845 188 6 6486 10 17313 10
|
||||||
|
9359 0 17017 3 17017 6 0 4 -48 101 -107 215 l-108 209 -115 0 -115 0 -46 88
|
||||||
|
c-25 48 -119 218 -209 377 -4411 7841 -11490 13891 -19905 17012 -3643 1351
|
||||||
|
-7473 2129 -11390 2313 -121 6 -337 15 -480 21 -334 13 -1963 20 -2335 9z"/>
|
||||||
|
<path d="M41748 58193 c23 -2 61 -2 85 0 23 2 4 4 -43 4 -47 0 -66 -2 -42 -4z"/>
|
||||||
|
<path d="M41907 58188 c2 -5 32 -8 66 -8 301 0 1251 -106 1839 -204 l258 -43
|
||||||
|
72 17 c50 12 67 19 53 23 -33 10 -476 74 -700 101 -439 53 -854 88 -1255 106
|
||||||
|
-135 6 -266 12 -292 13 -25 1 -44 -1 -41 -5z"/>
|
||||||
|
<path d="M40430 54743 c-1624 -71 -3107 -383 -4560 -960 -2369 -941 -4449
|
||||||
|
-2538 -5975 -4588 -1075 -1443 -1855 -3074 -2295 -4800 -225 -880 -339 -1606
|
||||||
|
-411 -2615 -17 -240 -23 -1104 -10 -1400 104 -2336 759 -4527 1948 -6508 473
|
||||||
|
-789 1012 -1514 1642 -2207 187 -206 690 -709 896 -896 1113 -1012 2358 -1825
|
||||||
|
3705 -2422 1405 -623 2913 -1007 4435 -1132 391 -32 492 -36 975 -42 651 -8
|
||||||
|
1130 14 1707 77 2901 318 5637 1563 7803 3550 197 181 684 669 861 865 1348
|
||||||
|
1483 2336 3187 2946 5080 313 972 522 2025 607 3055 37 443 41 553 41 1160 0
|
||||||
|
687 -14 971 -76 1525 -320 2894 -1530 5574 -3499 7750 -210 231 -704 725 -935
|
||||||
|
935 -1760 1592 -3852 2691 -6140 3225 -813 190 -1667 306 -2530 345 -194 9
|
||||||
|
-960 11 -1135 3z"/>
|
||||||
|
<path d="M55510 31687 c-77 -125 -361 -545 -495 -732 -384 -538 -807 -1065
|
||||||
|
-1246 -1551 l-116 -129 -265 -465 c-146 -256 -271 -476 -278 -490 l-13 -25 24
|
||||||
|
20 c13 11 5 -1 -18 -25 -44 -47 -299 -492 -9560 -16700 -2538 -4441 -4618
|
||||||
|
-8079 -4622 -8083 -17 -17 -1364 81 -1834 133 -84 10 -90 9 -177 -21 l-89 -31
|
||||||
|
-91 -154 c-50 -85 -88 -158 -86 -163 3 -4 36 -11 73 -15 37 -3 176 -17 308
|
||||||
|
-31 520 -55 1454 -129 1875 -150 63 -3 147 -8 186 -11 l71 -5 123 218 c150
|
||||||
|
264 1691 2960 4257 7448 1051 1837 2995 5237 4320 7555 1326 2318 3315 5797
|
||||||
|
4420 7730 1106 1933 2034 3556 2062 3605 28 50 314 551 636 1114 322 564 583
|
||||||
|
1026 582 1027 -2 2 -23 -29 -47 -69z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
BIN
logos/thorium.png
Normal file
After Width: | Height: | Size: 1.6 MiB |
247
media/gpu/gpu_video_decode_accelerator_factory.cc
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "media/gpu/gpu_video_decode_accelerator_factory.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "base/memory/ptr_util.h"
|
||||||
|
#include "base/threading/thread_task_runner_handle.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
|
#include "gpu/config/gpu_preferences.h"
|
||||||
|
#include "media/base/media_switches.h"
|
||||||
|
#include "media/gpu/buildflags.h"
|
||||||
|
#include "media/gpu/gpu_video_accelerator_util.h"
|
||||||
|
#include "media/gpu/macros.h"
|
||||||
|
#include "media/gpu/media_gpu_export.h"
|
||||||
|
#include "media/media_buildflags.h"
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
#include "base/win/windows_version.h"
|
||||||
|
#include "media/gpu/windows/dxva_video_decode_accelerator_win.h"
|
||||||
|
#endif
|
||||||
|
#if defined(OS_MAC)
|
||||||
|
#include "media/gpu/mac/vt_video_decode_accelerator_mac.h"
|
||||||
|
#endif
|
||||||
|
#if BUILDFLAG(USE_VAAPI)
|
||||||
|
#include "media/gpu/vaapi/vaapi_video_decode_accelerator.h"
|
||||||
|
#include "ui/gl/gl_implementation.h"
|
||||||
|
#elif BUILDFLAG(USE_V4L2_CODEC)
|
||||||
|
#include "media/gpu/v4l2/v4l2_device.h"
|
||||||
|
#include "media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h"
|
||||||
|
#include "media/gpu/v4l2/v4l2_video_decode_accelerator.h"
|
||||||
|
#include "ui/gl/gl_surface_egl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilitiesInternal(
|
||||||
|
const gpu::GpuPreferences& gpu_preferences,
|
||||||
|
const gpu::GpuDriverBugWorkarounds& workarounds) {
|
||||||
|
if (gpu_preferences.disable_accelerated_video_decode)
|
||||||
|
return gpu::VideoDecodeAcceleratorCapabilities();
|
||||||
|
|
||||||
|
// Query VDAs for their capabilities and construct a set of supported
|
||||||
|
// profiles for current platform. This must be done in the same order as in
|
||||||
|
// CreateVDA(), as we currently preserve additional capabilities (such as
|
||||||
|
// resolutions supported) only for the first VDA supporting the given codec
|
||||||
|
// profile (instead of calculating a superset).
|
||||||
|
// TODO(posciak,henryhsu): improve this so that we choose a superset of
|
||||||
|
// resolutions and other supported profile parameters.
|
||||||
|
VideoDecodeAccelerator::Capabilities capabilities;
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
capabilities.supported_profiles =
|
||||||
|
DXVAVideoDecodeAccelerator::GetSupportedProfiles(gpu_preferences,
|
||||||
|
workarounds);
|
||||||
|
#elif BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
|
||||||
|
#if BUILDFLAG(USE_VAAPI)
|
||||||
|
capabilities.supported_profiles =
|
||||||
|
VaapiVideoDecodeAccelerator::GetSupportedProfiles();
|
||||||
|
#elif BUILDFLAG(USE_V4L2_CODEC)
|
||||||
|
GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
|
||||||
|
V4L2VideoDecodeAccelerator::GetSupportedProfiles(),
|
||||||
|
&capabilities.supported_profiles);
|
||||||
|
GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
|
||||||
|
V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles(),
|
||||||
|
&capabilities.supported_profiles);
|
||||||
|
#endif
|
||||||
|
#elif defined(OS_MAC)
|
||||||
|
capabilities.supported_profiles =
|
||||||
|
VTVideoDecodeAccelerator::GetSupportedProfiles(workarounds);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeCapabilities(
|
||||||
|
capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// static
|
||||||
|
MEDIA_GPU_EXPORT std::unique_ptr<GpuVideoDecodeAcceleratorFactory>
|
||||||
|
GpuVideoDecodeAcceleratorFactory::Create(
|
||||||
|
const GpuVideoDecodeGLClient& gl_client) {
|
||||||
|
return base::WrapUnique(new GpuVideoDecodeAcceleratorFactory(gl_client));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
MEDIA_GPU_EXPORT gpu::VideoDecodeAcceleratorCapabilities
|
||||||
|
GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
|
||||||
|
const gpu::GpuPreferences& gpu_preferences,
|
||||||
|
const gpu::GpuDriverBugWorkarounds& workarounds) {
|
||||||
|
// Cache the capabilities so that they will not be computed more than once per
|
||||||
|
// GPU process. It is assumed that |gpu_preferences| and |workarounds| do not
|
||||||
|
// change between calls.
|
||||||
|
// TODO(sandersd): Move cache to GpuMojoMediaClient once
|
||||||
|
// |video_decode_accelerator_capabilities| is removed from GPUInfo.
|
||||||
|
static gpu::VideoDecodeAcceleratorCapabilities capabilities =
|
||||||
|
GetDecoderCapabilitiesInternal(gpu_preferences, workarounds);
|
||||||
|
|
||||||
|
#if BUILDFLAG(USE_V4L2_CODEC)
|
||||||
|
// V4L2-only: the decoder devices may not be visible at the time the GPU
|
||||||
|
// process is starting. If the capabilities vector is empty, try to query the
|
||||||
|
// devices again in the hope that they will have appeared in the meantime.
|
||||||
|
// TODO(crbug.com/948147): trigger query when an device add/remove event
|
||||||
|
// (e.g. via udev) has happened instead.
|
||||||
|
if (capabilities.supported_profiles.empty()) {
|
||||||
|
VLOGF(1) << "Capabilities empty, querying again...";
|
||||||
|
capabilities = GetDecoderCapabilitiesInternal(gpu_preferences, workarounds);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEDIA_GPU_EXPORT std::unique_ptr<VideoDecodeAccelerator>
|
||||||
|
GpuVideoDecodeAcceleratorFactory::CreateVDA(
|
||||||
|
VideoDecodeAccelerator::Client* client,
|
||||||
|
const VideoDecodeAccelerator::Config& config,
|
||||||
|
const gpu::GpuDriverBugWorkarounds& workarounds,
|
||||||
|
const gpu::GpuPreferences& gpu_preferences,
|
||||||
|
MediaLog* media_log) {
|
||||||
|
DCHECK(thread_checker_.CalledOnValidThread());
|
||||||
|
|
||||||
|
if (gpu_preferences.disable_accelerated_video_decode)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Array of Create..VDA() function pointers, potentially usable on current
|
||||||
|
// platform. This list is ordered by priority, from most to least preferred,
|
||||||
|
// if applicable. This list must be in the same order as the querying order
|
||||||
|
// in GetDecoderCapabilities() above.
|
||||||
|
using CreateVDAFp = std::unique_ptr<VideoDecodeAccelerator> (
|
||||||
|
GpuVideoDecodeAcceleratorFactory::*)(const gpu::GpuDriverBugWorkarounds&,
|
||||||
|
const gpu::GpuPreferences&,
|
||||||
|
MediaLog* media_log) const;
|
||||||
|
const CreateVDAFp create_vda_fps[] = {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
&GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Usually only one of USE_VAAPI or USE_V4L2_CODEC is defined on ChromeOS,
|
||||||
|
// except for Chromeboxes with companion video acceleration chips, which have
|
||||||
|
// both. In those cases prefer the VA creation function.
|
||||||
|
#if BUILDFLAG(USE_VAAPI)
|
||||||
|
&GpuVideoDecodeAcceleratorFactory::CreateVaapiVDA,
|
||||||
|
#elif BUILDFLAG(USE_V4L2_CODEC)
|
||||||
|
&GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA,
|
||||||
|
&GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_MAC)
|
||||||
|
&GpuVideoDecodeAcceleratorFactory::CreateVTVDA,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator> vda;
|
||||||
|
|
||||||
|
for (const auto& create_vda_function : create_vda_fps) {
|
||||||
|
vda = (this->*create_vda_function)(workarounds, gpu_preferences, media_log);
|
||||||
|
if (vda && vda->Initialize(config, client))
|
||||||
|
return vda;
|
||||||
|
else
|
||||||
|
LOG(ERROR) << "Initialization of one or more VDAs failed.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator>
|
||||||
|
GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA(
|
||||||
|
const gpu::GpuDriverBugWorkarounds& workarounds,
|
||||||
|
const gpu::GpuPreferences& gpu_preferences,
|
||||||
|
MediaLog* media_log) const {
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator> decoder;
|
||||||
|
DVLOG(0) << "Initializing DXVA HW decoder for windows.";
|
||||||
|
decoder.reset(new DXVAVideoDecodeAccelerator(
|
||||||
|
gl_client_.get_context, gl_client_.make_context_current,
|
||||||
|
gl_client_.bind_image, workarounds, gpu_preferences, media_log));
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BUILDFLAG(USE_VAAPI)
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator>
|
||||||
|
GpuVideoDecodeAcceleratorFactory::CreateVaapiVDA(
|
||||||
|
const gpu::GpuDriverBugWorkarounds& /*workarounds*/,
|
||||||
|
const gpu::GpuPreferences& /*gpu_preferences*/,
|
||||||
|
MediaLog* /*media_log*/) const {
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator> decoder;
|
||||||
|
decoder.reset(new VaapiVideoDecodeAccelerator(gl_client_.make_context_current,
|
||||||
|
gl_client_.bind_image));
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
#elif BUILDFLAG(USE_V4L2_CODEC)
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator>
|
||||||
|
GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA(
|
||||||
|
const gpu::GpuDriverBugWorkarounds& /*workarounds*/,
|
||||||
|
const gpu::GpuPreferences& /*gpu_preferences*/,
|
||||||
|
MediaLog* /*media_log*/) const {
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator> decoder;
|
||||||
|
scoped_refptr<V4L2Device> device = V4L2Device::Create();
|
||||||
|
if (device.get()) {
|
||||||
|
decoder.reset(new V4L2VideoDecodeAccelerator(
|
||||||
|
gl::GLSurfaceEGL::GetHardwareDisplay(), gl_client_.get_context,
|
||||||
|
gl_client_.make_context_current, device));
|
||||||
|
}
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator>
|
||||||
|
GpuVideoDecodeAcceleratorFactory::CreateV4L2SliceVDA(
|
||||||
|
const gpu::GpuDriverBugWorkarounds& /*workarounds*/,
|
||||||
|
const gpu::GpuPreferences& /*gpu_preferences*/,
|
||||||
|
MediaLog* /*media_log*/) const {
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator> decoder;
|
||||||
|
scoped_refptr<V4L2Device> device = V4L2Device::Create();
|
||||||
|
if (device.get()) {
|
||||||
|
decoder.reset(new V4L2SliceVideoDecodeAccelerator(
|
||||||
|
device, gl::GLSurfaceEGL::GetHardwareDisplay(), gl_client_.bind_image,
|
||||||
|
gl_client_.make_context_current));
|
||||||
|
}
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_MAC)
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator>
|
||||||
|
GpuVideoDecodeAcceleratorFactory::CreateVTVDA(
|
||||||
|
const gpu::GpuDriverBugWorkarounds& workarounds,
|
||||||
|
const gpu::GpuPreferences& gpu_preferences,
|
||||||
|
MediaLog* media_log) const {
|
||||||
|
LOG(WARNING) << "Initializing VAAPI VDA.";
|
||||||
|
std::unique_ptr<VideoDecodeAccelerator> decoder;
|
||||||
|
decoder.reset(
|
||||||
|
new VTVideoDecodeAccelerator(gl_client_, workarounds, media_log));
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GpuVideoDecodeAcceleratorFactory::GpuVideoDecodeAcceleratorFactory(
|
||||||
|
const GpuVideoDecodeGLClient& gl_client)
|
||||||
|
: gl_client_(gl_client) {}
|
||||||
|
GpuVideoDecodeAcceleratorFactory::~GpuVideoDecodeAcceleratorFactory() = default;
|
||||||
|
|
||||||
|
} // namespace media
|
622
media/gpu/ipc/service/gpu_video_decode_accelerator.cc
Normal file
|
@ -0,0 +1,622 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "base/location.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/memory/ref_counted.h"
|
||||||
|
#include "base/synchronization/waitable_event.h"
|
||||||
|
#include "base/task/bind_post_task.h"
|
||||||
|
#include "base/task/single_thread_task_runner.h"
|
||||||
|
#include "base/threading/thread_task_runner_handle.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
|
#include "gpu/command_buffer/common/command_buffer.h"
|
||||||
|
#include "gpu/config/gpu_preferences.h"
|
||||||
|
#include "gpu/ipc/service/gpu_channel.h"
|
||||||
|
#include "gpu/ipc/service/gpu_channel_manager.h"
|
||||||
|
#include "ipc/ipc_message_macros.h"
|
||||||
|
#include "ipc/ipc_message_utils.h"
|
||||||
|
#include "ipc/message_filter.h"
|
||||||
|
#include "media/base/limits.h"
|
||||||
|
#include "media/gpu/gpu_video_accelerator_util.h"
|
||||||
|
#include "media/gpu/gpu_video_decode_accelerator_factory.h"
|
||||||
|
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
||||||
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
#include "ui/gl/gl_context.h"
|
||||||
|
#include "ui/gl/gl_image.h"
|
||||||
|
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static gl::GLContext* GetGLContext(
|
||||||
|
const base::WeakPtr<gpu::CommandBufferStub>& stub) {
|
||||||
|
if (!stub) {
|
||||||
|
DLOG(ERROR) << "Stub is gone; no GLContext.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stub->decoder_context()->GetGLContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool MakeDecoderContextCurrent(
|
||||||
|
const base::WeakPtr<gpu::CommandBufferStub>& stub) {
|
||||||
|
if (!stub) {
|
||||||
|
DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stub->decoder_context()->MakeCurrent()) {
|
||||||
|
DLOG(ERROR) << "Failed to MakeCurrent()";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool BindImage(const base::WeakPtr<gpu::CommandBufferStub>& stub,
|
||||||
|
uint32_t client_texture_id,
|
||||||
|
uint32_t texture_target,
|
||||||
|
const scoped_refptr<gl::GLImage>& image,
|
||||||
|
bool can_bind_to_sampler) {
|
||||||
|
if (!stub) {
|
||||||
|
DLOG(ERROR) << "Stub is gone; won't BindImage().";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::DecoderContext* command_decoder = stub->decoder_context();
|
||||||
|
command_decoder->BindImage(client_texture_id, texture_target, image.get(),
|
||||||
|
can_bind_to_sampler);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpu::gles2::ContextGroup* GetContextGroup(
|
||||||
|
const base::WeakPtr<gpu::CommandBufferStub>& stub) {
|
||||||
|
if (!stub) {
|
||||||
|
DLOG(ERROR) << "Stub is gone; no DecoderContext.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stub->decoder_context()->GetContextGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unique_ptr<gpu::gles2::AbstractTexture> CreateAbstractTexture(
|
||||||
|
const base::WeakPtr<gpu::CommandBufferStub>& stub,
|
||||||
|
GLenum target,
|
||||||
|
GLenum internal_format,
|
||||||
|
GLsizei width,
|
||||||
|
GLsizei height,
|
||||||
|
GLsizei depth,
|
||||||
|
GLint border,
|
||||||
|
GLenum format,
|
||||||
|
GLenum type) {
|
||||||
|
if (!stub) {
|
||||||
|
DLOG(ERROR) << "Stub is gone; no DecoderContext.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stub->decoder_context()->CreateAbstractTexture(
|
||||||
|
target, internal_format, width, height, depth, border, format, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
// DebugAutoLock works like AutoLock but only acquires the lock when
|
||||||
|
// DCHECK is on.
|
||||||
|
#if DCHECK_IS_ON()
|
||||||
|
typedef base::AutoLock DebugAutoLock;
|
||||||
|
#else
|
||||||
|
class DebugAutoLock {
|
||||||
|
public:
|
||||||
|
explicit DebugAutoLock(base::Lock&) {}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Receives incoming messages for the decoder. Operates exclusively on the IO
|
||||||
|
// thread, since sometimes we want to do decodes directly from there.
|
||||||
|
class GpuVideoDecodeAccelerator::MessageFilter
|
||||||
|
: public mojom::GpuAcceleratedVideoDecoder {
|
||||||
|
public:
|
||||||
|
MessageFilter(GpuVideoDecodeAccelerator* owner,
|
||||||
|
scoped_refptr<base::SequencedTaskRunner> owner_task_runner,
|
||||||
|
bool decode_on_io)
|
||||||
|
: owner_(owner),
|
||||||
|
owner_task_runner_(std::move(owner_task_runner)),
|
||||||
|
decode_on_io_(decode_on_io) {}
|
||||||
|
~MessageFilter() override = default;
|
||||||
|
|
||||||
|
// Called from the main thread. Posts to `io_task_runner` to do the binding
|
||||||
|
// and waits for completion before returning. This ensures the decoder's
|
||||||
|
// endpoint is established before the synchronous request to establish it is
|
||||||
|
// acknowledged to the client.
|
||||||
|
bool Bind(mojo::PendingAssociatedReceiver<mojom::GpuAcceleratedVideoDecoder>
|
||||||
|
receiver,
|
||||||
|
const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
|
||||||
|
base::WaitableEvent bound_event;
|
||||||
|
if (!io_task_runner->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&MessageFilter::BindOnIoThread,
|
||||||
|
base::Unretained(this),
|
||||||
|
std::move(receiver), &bound_event))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bound_event.Wait();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be called on the IO thread. Posts back to the owner's task runner to
|
||||||
|
// destroy it.
|
||||||
|
void RequestShutdown() {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Must be reset here on the IO thread before `this` is destroyed.
|
||||||
|
receiver_.reset();
|
||||||
|
|
||||||
|
GpuVideoDecodeAccelerator* owner = owner_;
|
||||||
|
owner_ = nullptr;
|
||||||
|
|
||||||
|
// Invalidate any IO thread WeakPtrs which may be held by the
|
||||||
|
// VideoDecodeAccelerator, and post to delete our owner which will in turn
|
||||||
|
// delete us. Note that it is unsafe to access any members of `this` once
|
||||||
|
// the task below is posted.
|
||||||
|
owner->weak_factory_for_io_.InvalidateWeakPtrs();
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::DeleteSelfNow,
|
||||||
|
base::Unretained(owner)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// mojom::GpuAcceleratedVideoDecoder:
|
||||||
|
void Decode(BitstreamBuffer buffer) override;
|
||||||
|
void AssignPictureBuffers(
|
||||||
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments) override;
|
||||||
|
void ReusePictureBuffer(int32_t picture_buffer_id) override;
|
||||||
|
void Flush(FlushCallback callback) override;
|
||||||
|
void Reset(ResetCallback callback) override;
|
||||||
|
void SetOverlayInfo(const OverlayInfo& overlay_info) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void BindOnIoThread(mojo::PendingAssociatedReceiver<
|
||||||
|
mojom::GpuAcceleratedVideoDecoder> receiver,
|
||||||
|
base::WaitableEvent* bound_event) {
|
||||||
|
receiver_.Bind(std::move(receiver));
|
||||||
|
receiver_.set_disconnect_handler(
|
||||||
|
base::BindOnce(&MessageFilter::OnDisconnect, base::Unretained(this)));
|
||||||
|
bound_event->Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDisconnect() {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnDestroy,
|
||||||
|
base::Unretained(owner_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
GpuVideoDecodeAccelerator* owner_;
|
||||||
|
const scoped_refptr<base::SequencedTaskRunner> owner_task_runner_;
|
||||||
|
const bool decode_on_io_;
|
||||||
|
mojo::AssociatedReceiver<mojom::GpuAcceleratedVideoDecoder> receiver_{this};
|
||||||
|
};
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::Decode(BitstreamBuffer buffer) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (decode_on_io_) {
|
||||||
|
owner_->OnDecode(std::move(buffer));
|
||||||
|
} else {
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnDecode,
|
||||||
|
base::Unretained(owner_), std::move(buffer)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::AssignPictureBuffers(
|
||||||
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::BindOnce(&GpuVideoDecodeAccelerator::OnAssignPictureBuffers,
|
||||||
|
base::Unretained(owner_), std::move(assignments)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::ReusePictureBuffer(
|
||||||
|
int32_t picture_buffer_id) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
base::BindOnce(&GpuVideoDecodeAccelerator::OnReusePictureBuffer,
|
||||||
|
base::Unretained(owner_), picture_buffer_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::Flush(FlushCallback callback) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnFlush,
|
||||||
|
base::Unretained(owner_), std::move(callback)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::Reset(ResetCallback callback) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnReset,
|
||||||
|
base::Unretained(owner_), std::move(callback)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::MessageFilter::SetOverlayInfo(
|
||||||
|
const OverlayInfo& overlay_info) {
|
||||||
|
if (!owner_)
|
||||||
|
return;
|
||||||
|
owner_task_runner_->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&GpuVideoDecodeAccelerator::OnSetOverlayInfo,
|
||||||
|
base::Unretained(owner_), overlay_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
|
||||||
|
gpu::CommandBufferStub* stub,
|
||||||
|
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
|
||||||
|
const AndroidOverlayMojoFactoryCB& overlay_factory_cb)
|
||||||
|
: stub_(stub),
|
||||||
|
texture_target_(0),
|
||||||
|
pixel_format_(PIXEL_FORMAT_UNKNOWN),
|
||||||
|
textures_per_buffer_(0),
|
||||||
|
child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
||||||
|
io_task_runner_(io_task_runner),
|
||||||
|
overlay_factory_cb_(overlay_factory_cb) {
|
||||||
|
DCHECK(stub_);
|
||||||
|
stub_->AddDestructionObserver(this);
|
||||||
|
gl_client_.get_context =
|
||||||
|
base::BindRepeating(&GetGLContext, stub_->AsWeakPtr());
|
||||||
|
gl_client_.make_context_current =
|
||||||
|
base::BindRepeating(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
|
||||||
|
gl_client_.bind_image = base::BindRepeating(&BindImage, stub_->AsWeakPtr());
|
||||||
|
gl_client_.get_context_group =
|
||||||
|
base::BindRepeating(&GetContextGroup, stub_->AsWeakPtr());
|
||||||
|
gl_client_.create_abstract_texture =
|
||||||
|
base::BindRepeating(&CreateAbstractTexture, stub_->AsWeakPtr());
|
||||||
|
gl_client_.is_passthrough =
|
||||||
|
stub_->decoder_context()->GetFeatureInfo()->is_passthrough_cmd_decoder();
|
||||||
|
gl_client_.supports_arb_texture_rectangle = stub_->decoder_context()
|
||||||
|
->GetFeatureInfo()
|
||||||
|
->feature_flags()
|
||||||
|
.arb_texture_rectangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
|
||||||
|
// This class can only be self-deleted from OnWillDestroyStub(), which means
|
||||||
|
// the VDA has already been destroyed in there.
|
||||||
|
DCHECK(!video_decode_accelerator_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::DeleteSelfNow() {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
gpu::VideoDecodeAcceleratorCapabilities
|
||||||
|
GpuVideoDecodeAccelerator::GetCapabilities(
|
||||||
|
const gpu::GpuPreferences& gpu_preferences,
|
||||||
|
const gpu::GpuDriverBugWorkarounds& workarounds) {
|
||||||
|
return GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities(
|
||||||
|
gpu_preferences, workarounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::NotifyInitializationComplete(Status status) {
|
||||||
|
decoder_client_->OnInitializationComplete(status.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
|
||||||
|
uint32_t requested_num_of_buffers,
|
||||||
|
VideoPixelFormat format,
|
||||||
|
uint32_t textures_per_buffer,
|
||||||
|
const gfx::Size& dimensions,
|
||||||
|
uint32_t texture_target) {
|
||||||
|
if (dimensions.width() > limits::kMaxDimension ||
|
||||||
|
dimensions.height() > limits::kMaxDimension ||
|
||||||
|
dimensions.GetArea() > limits::kMaxCanvas) {
|
||||||
|
NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture_dimensions_ = dimensions;
|
||||||
|
textures_per_buffer_ = textures_per_buffer;
|
||||||
|
texture_target_ = texture_target;
|
||||||
|
pixel_format_ = format;
|
||||||
|
|
||||||
|
decoder_client_->OnProvidePictureBuffers(requested_num_of_buffers, format,
|
||||||
|
textures_per_buffer, dimensions,
|
||||||
|
texture_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::DismissPictureBuffer(
|
||||||
|
int32_t picture_buffer_id) {
|
||||||
|
// Notify client that picture buffer is now unused.
|
||||||
|
decoder_client_->OnDismissPictureBuffer(picture_buffer_id);
|
||||||
|
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
||||||
|
uncleared_textures_.erase(picture_buffer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::PictureReady(const Picture& picture) {
|
||||||
|
// VDA may call PictureReady on IO thread. SetTextureCleared should run on
|
||||||
|
// the child thread. VDA is responsible to call PictureReady on the child
|
||||||
|
// thread when a picture buffer is delivered the first time.
|
||||||
|
if (child_task_runner_->BelongsToCurrentThread()) {
|
||||||
|
SetTextureCleared(picture);
|
||||||
|
} else {
|
||||||
|
DCHECK(io_task_runner_->BelongsToCurrentThread());
|
||||||
|
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
||||||
|
DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto params = mojom::PictureReadyParams::New();
|
||||||
|
params->picture_buffer_id = picture.picture_buffer_id();
|
||||||
|
params->bitstream_buffer_id = picture.bitstream_buffer_id();
|
||||||
|
params->visible_rect = picture.visible_rect();
|
||||||
|
params->color_space = picture.color_space();
|
||||||
|
params->allow_overlay = picture.allow_overlay();
|
||||||
|
params->read_lock_fences_enabled = picture.read_lock_fences_enabled();
|
||||||
|
params->size_changed = picture.size_changed();
|
||||||
|
params->surface_texture = picture.texture_owner();
|
||||||
|
params->wants_promotion_hint = picture.wants_promotion_hint();
|
||||||
|
decoder_client_->OnPictureReady(std::move(params));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
|
||||||
|
int32_t bitstream_buffer_id) {
|
||||||
|
decoder_client_->OnBitstreamBufferProcessed(bitstream_buffer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::NotifyFlushDone() {
|
||||||
|
DCHECK(!pending_flushes_.empty());
|
||||||
|
std::move(pending_flushes_.front()).Run();
|
||||||
|
pending_flushes_.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::NotifyResetDone() {
|
||||||
|
DCHECK(!pending_resets_.empty());
|
||||||
|
std::move(pending_resets_.front()).Run();
|
||||||
|
pending_resets_.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::NotifyError(
|
||||||
|
VideoDecodeAccelerator::Error error) {
|
||||||
|
decoder_client_->OnError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::OnWillDestroyStub(bool have_context) {
|
||||||
|
// The stub is going away, so we have to stop and destroy VDA here, before
|
||||||
|
// returning, because the VDA may need the GL context to run and/or do its
|
||||||
|
// cleanup. We cannot destroy the VDA before the IO thread message filter is
|
||||||
|
// removed however, since we cannot service incoming messages with VDA gone.
|
||||||
|
// We cannot simply check for existence of VDA on IO thread though, because
|
||||||
|
// we don't want to synchronize the IO thread with the ChildThread.
|
||||||
|
// So we have to wait for the RemoveFilter callback here instead and remove
|
||||||
|
// the VDA after it arrives and before returning.
|
||||||
|
stub_->RemoveDestructionObserver(this);
|
||||||
|
if (filter_) {
|
||||||
|
io_task_runner_->PostTask(FROM_HERE,
|
||||||
|
base::BindOnce(&MessageFilter::RequestShutdown,
|
||||||
|
base::Unretained(filter_.get())));
|
||||||
|
}
|
||||||
|
|
||||||
|
video_decode_accelerator_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GpuVideoDecodeAccelerator::Initialize(
|
||||||
|
const VideoDecodeAccelerator::Config& config,
|
||||||
|
mojo::PendingAssociatedReceiver<mojom::GpuAcceleratedVideoDecoder> receiver,
|
||||||
|
mojo::PendingAssociatedRemote<mojom::GpuAcceleratedVideoDecoderClient>
|
||||||
|
client) {
|
||||||
|
DCHECK(!video_decode_accelerator_);
|
||||||
|
|
||||||
|
#if !defined(OS_WIN)
|
||||||
|
// Ensure we will be able to get a GL context at all before initializing
|
||||||
|
// non-Windows VDAs.
|
||||||
|
if (!gl_client_.make_context_current.Run())
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::unique_ptr<GpuVideoDecodeAcceleratorFactory> vda_factory =
|
||||||
|
GpuVideoDecodeAcceleratorFactory::Create(gl_client_);
|
||||||
|
if (!vda_factory) {
|
||||||
|
LOG(ERROR) << "Failed creating the VDA factory";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG(WARNING) << "Created the VDA factory";
|
||||||
|
|
||||||
|
const gpu::GpuDriverBugWorkarounds& gpu_workarounds =
|
||||||
|
stub_->channel()->gpu_channel_manager()->gpu_driver_bug_workarounds();
|
||||||
|
const gpu::GpuPreferences& gpu_preferences =
|
||||||
|
stub_->channel()->gpu_channel_manager()->gpu_preferences();
|
||||||
|
|
||||||
|
if (config.output_mode !=
|
||||||
|
VideoDecodeAccelerator::Config::OutputMode::ALLOCATE) {
|
||||||
|
DLOG(ERROR) << "Only ALLOCATE mode is supported";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
video_decode_accelerator_ =
|
||||||
|
vda_factory->CreateVDA(this, config, gpu_workarounds, gpu_preferences);
|
||||||
|
if (!video_decode_accelerator_) {
|
||||||
|
LOG(ERROR) << "HW video decode not available for profile "
|
||||||
|
<< GetProfileName(config.profile)
|
||||||
|
<< (config.is_encrypted() ? " with encryption" : "");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG(WARNING) << "Created VDA";
|
||||||
|
|
||||||
|
decoder_client_.Bind(std::move(client), io_task_runner_);
|
||||||
|
|
||||||
|
// Attempt to set up performing decoding tasks on IO thread, if supported by
|
||||||
|
// the VDA.
|
||||||
|
bool decode_on_io =
|
||||||
|
video_decode_accelerator_->TryToSetupDecodeOnSeparateThread(
|
||||||
|
weak_factory_for_io_.GetWeakPtr(), io_task_runner_);
|
||||||
|
|
||||||
|
// Bind the receiver on the IO thread. We wait here for it to be bound
|
||||||
|
// before returning and signaling that the decoder has been created.
|
||||||
|
filter_ =
|
||||||
|
std::make_unique<MessageFilter>(this, stub_->task_runner(), decode_on_io);
|
||||||
|
return filter_->Bind(std::move(receiver), io_task_runner_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runs on IO thread if VDA::TryToSetupDecodeOnSeparateThread() succeeded,
|
||||||
|
// otherwise on the main thread.
|
||||||
|
void GpuVideoDecodeAccelerator::OnDecode(BitstreamBuffer bitstream_buffer) {
|
||||||
|
DCHECK(video_decode_accelerator_);
|
||||||
|
video_decode_accelerator_->Decode(std::move(bitstream_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
||||||
|
std::vector<mojom::PictureBufferAssignmentPtr> assignments) {
|
||||||
|
gpu::DecoderContext* decoder_context = stub_->decoder_context();
|
||||||
|
gpu::gles2::TextureManager* texture_manager =
|
||||||
|
stub_->decoder_context()->GetContextGroup()->texture_manager();
|
||||||
|
|
||||||
|
std::vector<PictureBuffer> buffers;
|
||||||
|
std::vector<std::vector<scoped_refptr<gpu::gles2::TextureRef>>> textures;
|
||||||
|
for (const auto& assignment : assignments) {
|
||||||
|
if (assignment->buffer_id < 0) {
|
||||||
|
DLOG(ERROR) << "Buffer id " << assignment->buffer_id << " out of range";
|
||||||
|
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::vector<scoped_refptr<gpu::gles2::TextureRef>> current_textures;
|
||||||
|
PictureBuffer::TextureIds buffer_texture_ids = assignment->texture_ids;
|
||||||
|
PictureBuffer::TextureIds service_ids;
|
||||||
|
if (buffer_texture_ids.size() != textures_per_buffer_) {
|
||||||
|
DLOG(ERROR) << "Requested " << textures_per_buffer_
|
||||||
|
<< " textures per picture buffer, got "
|
||||||
|
<< buffer_texture_ids.size();
|
||||||
|
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < textures_per_buffer_; j++) {
|
||||||
|
gpu::TextureBase* texture_base =
|
||||||
|
decoder_context->GetTextureBase(buffer_texture_ids[j]);
|
||||||
|
if (!texture_base) {
|
||||||
|
DLOG(ERROR) << "Failed to find texture id " << buffer_texture_ids[j];
|
||||||
|
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_base->target() != texture_target_) {
|
||||||
|
DLOG(ERROR) << "Texture target mismatch for texture id "
|
||||||
|
<< buffer_texture_ids[j];
|
||||||
|
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_manager) {
|
||||||
|
gpu::gles2::TextureRef* texture_ref =
|
||||||
|
texture_manager->GetTexture(buffer_texture_ids[j]);
|
||||||
|
if (texture_ref) {
|
||||||
|
gpu::gles2::Texture* info = texture_ref->texture();
|
||||||
|
if (texture_target_ == GL_TEXTURE_EXTERNAL_OES ||
|
||||||
|
texture_target_ == GL_TEXTURE_RECTANGLE_ARB) {
|
||||||
|
// These textures have their dimensions defined by the underlying
|
||||||
|
// storage.
|
||||||
|
// Use |texture_dimensions_| for this size.
|
||||||
|
texture_manager->SetLevelInfo(
|
||||||
|
texture_ref, texture_target_, 0, GL_RGBA,
|
||||||
|
texture_dimensions_.width(), texture_dimensions_.height(), 1, 0,
|
||||||
|
GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect());
|
||||||
|
} else {
|
||||||
|
// For other targets, texture dimensions should already be defined.
|
||||||
|
GLsizei width = 0, height = 0;
|
||||||
|
info->GetLevelSize(texture_target_, 0, &width, &height, nullptr);
|
||||||
|
if (width != texture_dimensions_.width() ||
|
||||||
|
height != texture_dimensions_.height()) {
|
||||||
|
DLOG(ERROR) << "Size mismatch for texture id "
|
||||||
|
<< buffer_texture_ids[j];
|
||||||
|
NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(dshwang): after moving to D3D11, remove this.
|
||||||
|
// https://crbug.com/438691
|
||||||
|
GLenum format =
|
||||||
|
video_decode_accelerator_->GetSurfaceInternalFormat();
|
||||||
|
if (format != GL_RGBA) {
|
||||||
|
DCHECK(format == GL_BGRA_EXT);
|
||||||
|
texture_manager->SetLevelInfo(texture_ref, texture_target_, 0,
|
||||||
|
format, width, height, 1, 0, format,
|
||||||
|
GL_UNSIGNED_BYTE, gfx::Rect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_textures.push_back(texture_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service_ids.push_back(texture_base->service_id());
|
||||||
|
}
|
||||||
|
textures.push_back(current_textures);
|
||||||
|
buffers.emplace_back(assignment->buffer_id, texture_dimensions_,
|
||||||
|
buffer_texture_ids, service_ids, texture_target_,
|
||||||
|
pixel_format_);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
||||||
|
for (uint32_t i = 0; i < assignments.size(); ++i)
|
||||||
|
uncleared_textures_[assignments[i]->buffer_id] = textures[i];
|
||||||
|
}
|
||||||
|
video_decode_accelerator_->AssignPictureBuffers(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::OnReusePictureBuffer(
|
||||||
|
int32_t picture_buffer_id) {
|
||||||
|
DCHECK(video_decode_accelerator_);
|
||||||
|
video_decode_accelerator_->ReusePictureBuffer(picture_buffer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::OnFlush(base::OnceClosure callback) {
|
||||||
|
DCHECK(video_decode_accelerator_);
|
||||||
|
pending_flushes_.push_back(
|
||||||
|
base::BindPostTask(io_task_runner_, std::move(callback)));
|
||||||
|
video_decode_accelerator_->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::OnReset(base::OnceClosure callback) {
|
||||||
|
DCHECK(video_decode_accelerator_);
|
||||||
|
pending_resets_.push_back(
|
||||||
|
base::BindPostTask(io_task_runner_, std::move(callback)));
|
||||||
|
video_decode_accelerator_->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::OnSetOverlayInfo(
|
||||||
|
const OverlayInfo& overlay_info) {
|
||||||
|
DCHECK(video_decode_accelerator_);
|
||||||
|
video_decode_accelerator_->SetOverlayInfo(overlay_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::OnDestroy() {
|
||||||
|
DCHECK(video_decode_accelerator_);
|
||||||
|
OnWillDestroyStub(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GpuVideoDecodeAccelerator::SetTextureCleared(const Picture& picture) {
|
||||||
|
DCHECK(child_task_runner_->BelongsToCurrentThread());
|
||||||
|
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
||||||
|
auto it = uncleared_textures_.find(picture.picture_buffer_id());
|
||||||
|
if (it == uncleared_textures_.end())
|
||||||
|
return; // the texture has been cleared
|
||||||
|
|
||||||
|
for (auto texture_ref : it->second) {
|
||||||
|
GLenum target = texture_ref->texture()->target();
|
||||||
|
gpu::gles2::TextureManager* texture_manager =
|
||||||
|
stub_->decoder_context()->GetContextGroup()->texture_manager();
|
||||||
|
texture_manager->SetLevelCleared(texture_ref.get(), target, 0, true);
|
||||||
|
}
|
||||||
|
uncleared_textures_.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace media
|
1321
media/gpu/vaapi/vaapi_video_decode_accelerator.cc
Normal file
368
media/gpu/vaapi/vaapi_video_decode_accelerator.h
Normal file
|
@ -0,0 +1,368 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// This file contains an implementation of VideoDecoderAccelerator
|
||||||
|
// that utilizes hardware video decoder present on Intel CPUs.
|
||||||
|
|
||||||
|
#ifndef MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
|
||||||
|
#define MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/containers/queue.h"
|
||||||
|
#include "base/containers/small_map.h"
|
||||||
|
#include "base/macros.h"
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
#include "base/synchronization/condition_variable.h"
|
||||||
|
#include "base/synchronization/lock.h"
|
||||||
|
#include "base/task/single_thread_task_runner.h"
|
||||||
|
#include "base/thread_annotations.h"
|
||||||
|
#include "base/threading/thread.h"
|
||||||
|
#include "base/trace_event/memory_dump_provider.h"
|
||||||
|
#include "media/base/bitstream_buffer.h"
|
||||||
|
#include "media/gpu/decode_surface_handler.h"
|
||||||
|
#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
|
||||||
|
#include "media/gpu/media_gpu_export.h"
|
||||||
|
#include "media/gpu/vaapi/vaapi_picture_factory.h"
|
||||||
|
#include "media/gpu/vaapi/vaapi_wrapper.h"
|
||||||
|
#include "media/video/picture.h"
|
||||||
|
#include "media/video/video_decode_accelerator.h"
|
||||||
|
|
||||||
|
namespace gl {
|
||||||
|
class GLImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
class AcceleratedVideoDecoder;
|
||||||
|
template <typename T>
|
||||||
|
class ScopedID;
|
||||||
|
class VaapiVideoDecoderDelegate;
|
||||||
|
class VaapiPicture;
|
||||||
|
|
||||||
|
// Class to provide video decode acceleration for Intel systems with hardware
|
||||||
|
// support for it, and on which libva is available.
|
||||||
|
// Decoding tasks are performed in a separate decoding thread.
|
||||||
|
//
|
||||||
|
// Threading/life-cycle: this object is created & destroyed on the GPU
|
||||||
|
// ChildThread. A few methods on it are called on the decoder thread which is
|
||||||
|
// stopped during |this->Destroy()|, so any tasks posted to the decoder thread
|
||||||
|
// can assume |*this| is still alive. See |weak_this_| below for more details.
|
||||||
|
class MEDIA_GPU_EXPORT VaapiVideoDecodeAccelerator
|
||||||
|
: public VideoDecodeAccelerator,
|
||||||
|
public DecodeSurfaceHandler<VASurface>,
|
||||||
|
public base::trace_event::MemoryDumpProvider {
|
||||||
|
public:
|
||||||
|
VaapiVideoDecodeAccelerator(
|
||||||
|
const MakeGLContextCurrentCallback& make_context_current_cb,
|
||||||
|
const BindGLImageCallback& bind_image_cb);
|
||||||
|
|
||||||
|
VaapiVideoDecodeAccelerator(const VaapiVideoDecodeAccelerator&) = delete;
|
||||||
|
VaapiVideoDecodeAccelerator& operator=(const VaapiVideoDecodeAccelerator&) =
|
||||||
|
delete;
|
||||||
|
|
||||||
|
~VaapiVideoDecodeAccelerator() override;
|
||||||
|
|
||||||
|
// VideoDecodeAccelerator implementation.
|
||||||
|
bool Initialize(const Config& config, Client* client) override;
|
||||||
|
void Decode(BitstreamBuffer bitstream_buffer) override;
|
||||||
|
void Decode(scoped_refptr<DecoderBuffer> buffer,
|
||||||
|
int32_t bitstream_id) override;
|
||||||
|
void AssignPictureBuffers(const std::vector<PictureBuffer>& buffers) override;
|
||||||
|
#if defined(USE_OZONE)
|
||||||
|
void ImportBufferForPicture(
|
||||||
|
int32_t picture_buffer_id,
|
||||||
|
VideoPixelFormat pixel_format,
|
||||||
|
gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) override;
|
||||||
|
#endif
|
||||||
|
void ReusePictureBuffer(int32_t picture_buffer_id) override;
|
||||||
|
void Flush() override;
|
||||||
|
void Reset() override;
|
||||||
|
void Destroy() override;
|
||||||
|
bool TryToSetupDecodeOnSeparateThread(
|
||||||
|
const base::WeakPtr<Client>& decode_client,
|
||||||
|
const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
|
||||||
|
override;
|
||||||
|
|
||||||
|
static VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles();
|
||||||
|
|
||||||
|
static bool IsVppProfileSupported();
|
||||||
|
|
||||||
|
// DecodeSurfaceHandler implementation.
|
||||||
|
scoped_refptr<VASurface> CreateSurface() override;
|
||||||
|
void SurfaceReady(scoped_refptr<VASurface> va_surface,
|
||||||
|
int32_t bitstream_id,
|
||||||
|
const gfx::Rect& visible_rect,
|
||||||
|
const VideoColorSpace& color_space) override;
|
||||||
|
|
||||||
|
// base::trace_event::MemoryDumpProvider implementation.
|
||||||
|
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
|
||||||
|
base::trace_event::ProcessMemoryDump* pmd) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class VaapiVideoDecodeAcceleratorTest;
|
||||||
|
|
||||||
|
// An input buffer with id provided by the client and awaiting consumption.
|
||||||
|
class InputBuffer;
|
||||||
|
// A self-cleaning VASurfaceID.
|
||||||
|
using ScopedVASurfaceID = ScopedID<VASurfaceID>;
|
||||||
|
|
||||||
|
// Notify the client that an error has occurred and decoding cannot continue.
|
||||||
|
void NotifyError(Error error);
|
||||||
|
void NotifyStatus(VaapiStatus status);
|
||||||
|
|
||||||
|
// Queue a input buffer for decode.
|
||||||
|
void QueueInputBuffer(scoped_refptr<DecoderBuffer> buffer,
|
||||||
|
int32_t bitstream_id);
|
||||||
|
|
||||||
|
// Gets a new |current_input_buffer_| from |input_buffers_| and sets it up in
|
||||||
|
// |decoder_|. This method will sleep if no |input_buffers_| are available.
|
||||||
|
// Returns true if a new buffer has been set up, false if an early exit has
|
||||||
|
// been requested (due to initiated reset/flush/destroy).
|
||||||
|
bool GetCurrInputBuffer_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||||
|
|
||||||
|
// Signals the client that |curr_input_buffer_| has been read and can be
|
||||||
|
// returned. Will also release the mapping.
|
||||||
|
void ReturnCurrInputBuffer_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||||
|
|
||||||
|
// Waits for more surfaces to become available. Returns true once they do or
|
||||||
|
// false if an early exit has been requested (due to an initiated
|
||||||
|
// reset/flush/destroy).
|
||||||
|
bool WaitForSurfaces_Locked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
|
||||||
|
|
||||||
|
// Continue decoding given input buffers and sleep waiting for input/output
|
||||||
|
// as needed. Will exit if a new set of surfaces or reset/flush/destroy
|
||||||
|
// is requested.
|
||||||
|
void DecodeTask();
|
||||||
|
|
||||||
|
// Scheduled after receiving a flush request and executed after the current
|
||||||
|
// decoding task finishes decoding pending inputs. Makes the decoder return
|
||||||
|
// all remaining output pictures and puts it in an idle state, ready
|
||||||
|
// to resume if needed and schedules a FinishFlush.
|
||||||
|
void FlushTask();
|
||||||
|
|
||||||
|
// Scheduled by the FlushTask after decoder is flushed to put VAVDA into idle
|
||||||
|
// state and notify the client that flushing has been finished.
|
||||||
|
void FinishFlush();
|
||||||
|
|
||||||
|
// Scheduled after receiving a reset request and executed after the current
|
||||||
|
// decoding task finishes decoding the current frame. Puts the decoder into
|
||||||
|
// an idle state, ready to resume if needed, discarding decoded but not yet
|
||||||
|
// outputted pictures (decoder keeps ownership of their associated picture
|
||||||
|
// buffers). Schedules a FinishReset afterwards.
|
||||||
|
void ResetTask();
|
||||||
|
|
||||||
|
// Scheduled by ResetTask after it's done putting VAVDA into an idle state.
|
||||||
|
// Drops remaining input buffers and notifies the client that reset has been
|
||||||
|
// finished.
|
||||||
|
void FinishReset();
|
||||||
|
|
||||||
|
// Helper for Destroy(), doing all the actual work except for deleting self.
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
// Get a usable framebuffer configuration for use in binding textures
|
||||||
|
// or return false on failure.
|
||||||
|
bool InitializeFBConfig();
|
||||||
|
|
||||||
|
// Callback to be executed once we have a |va_surface| to be output and an
|
||||||
|
// available VaapiPicture in |available_picture_buffers_| for output. Puts
|
||||||
|
// contents of |va_surface| into the latter, releases the surface and passes
|
||||||
|
// the resulting picture to |client_| along with |visible_rect|.
|
||||||
|
void OutputPicture(scoped_refptr<VASurface> va_surface,
|
||||||
|
int32_t input_id,
|
||||||
|
gfx::Rect visible_rect,
|
||||||
|
const VideoColorSpace& picture_color_space);
|
||||||
|
|
||||||
|
// Try to OutputPicture() if we have both a ready surface and picture.
|
||||||
|
void TryOutputPicture();
|
||||||
|
|
||||||
|
// Called when a VASurface is no longer in use by |decoder_| nor |client_|.
|
||||||
|
// Returns it to |available_va_surfaces_|. |va_surface_id| is not used but it
|
||||||
|
// must be here to bind this method as VASurface::ReleaseCB.
|
||||||
|
void RecycleVASurface(std::unique_ptr<ScopedVASurfaceID> va_surface,
|
||||||
|
VASurfaceID va_surface_id);
|
||||||
|
|
||||||
|
// Request a new set of |num_pics| PictureBuffers to be allocated by
|
||||||
|
// |client_|. Up to |num_reference_frames| out of |num_pics_| might be needed
|
||||||
|
// by |decoder_|.
|
||||||
|
void InitiateSurfaceSetChange(size_t num_pics,
|
||||||
|
gfx::Size size,
|
||||||
|
size_t num_reference_frames,
|
||||||
|
const gfx::Rect& visible_rect);
|
||||||
|
|
||||||
|
// Check if the surfaces have been released or post ourselves for later.
|
||||||
|
void TryFinishSurfaceSetChange();
|
||||||
|
|
||||||
|
// Different modes of internal buffer allocations.
|
||||||
|
enum class BufferAllocationMode {
|
||||||
|
// Only using |client_|s provided PictureBuffers, none internal.
|
||||||
|
kNone,
|
||||||
|
|
||||||
|
// Using a reduced amount of |client_|s provided PictureBuffers and
|
||||||
|
// |decoder_|s GetNumReferenceFrames() internallly.
|
||||||
|
kSuperReduced,
|
||||||
|
|
||||||
|
// Similar to kSuperReduced, but we have to increase slightly the amount of
|
||||||
|
// PictureBuffers allocated for the |client_|.
|
||||||
|
kReduced,
|
||||||
|
|
||||||
|
// VaapiVideoDecodeAccelerator can work with this mode on all platforms.
|
||||||
|
// Using |client_|s provided PictureBuffers and as many internally
|
||||||
|
// allocated.
|
||||||
|
kNormal,
|
||||||
|
kWrapVdpau,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Decides the concrete buffer allocation mode, depending on the hardware
|
||||||
|
// platform and other parameters.
|
||||||
|
BufferAllocationMode DecideBufferAllocationMode();
|
||||||
|
bool IsBufferAllocationModeReducedOrSuperReduced() const;
|
||||||
|
|
||||||
|
// VAVDA state.
|
||||||
|
enum State {
|
||||||
|
// Initialize() not called yet or failed.
|
||||||
|
kUninitialized,
|
||||||
|
// DecodeTask running.
|
||||||
|
kDecoding,
|
||||||
|
// Resetting, waiting for decoder to finish current task and cleanup.
|
||||||
|
kResetting,
|
||||||
|
// Idle, decoder in state ready to start/resume decoding.
|
||||||
|
kIdle,
|
||||||
|
// Destroying, waiting for the decoder to finish current task.
|
||||||
|
kDestroying,
|
||||||
|
};
|
||||||
|
|
||||||
|
base::Lock lock_;
|
||||||
|
State state_ GUARDED_BY(lock_);
|
||||||
|
// Only used on |task_runner_|.
|
||||||
|
Config::OutputMode output_mode_;
|
||||||
|
|
||||||
|
// Queue of available InputBuffers.
|
||||||
|
base::queue<std::unique_ptr<InputBuffer>> input_buffers_ GUARDED_BY(lock_);
|
||||||
|
// Signalled when input buffers are queued onto |input_buffers_| queue.
|
||||||
|
base::ConditionVariable input_ready_;
|
||||||
|
|
||||||
|
// Current input buffer at decoder. Only used on |decoder_thread_task_runner_|
|
||||||
|
std::unique_ptr<InputBuffer> curr_input_buffer_;
|
||||||
|
|
||||||
|
// Only used on |task_runner_|.
|
||||||
|
std::unique_ptr<VaapiPictureFactory> vaapi_picture_factory_;
|
||||||
|
|
||||||
|
// The following variables are constructed/initialized in Initialize() when
|
||||||
|
// the codec information is received. |vaapi_wrapper_| is thread safe.
|
||||||
|
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
|
||||||
|
// Only used on |decoder_thread_task_runner_|.
|
||||||
|
std::unique_ptr<AcceleratedVideoDecoder> decoder_;
|
||||||
|
// TODO(crbug.com/1022246): Instead of having the raw pointer here, getting
|
||||||
|
// the pointer from AcceleratedVideoDecoder.
|
||||||
|
VaapiVideoDecoderDelegate* decoder_delegate_ = nullptr;
|
||||||
|
|
||||||
|
// Filled in during Initialize().
|
||||||
|
BufferAllocationMode buffer_allocation_mode_;
|
||||||
|
|
||||||
|
// VaapiWrapper for VPP (Video Post Processing). This is used for copying
|
||||||
|
// from a decoded surface to a surface bound to client's PictureBuffer.
|
||||||
|
scoped_refptr<VaapiWrapper> vpp_vaapi_wrapper_;
|
||||||
|
|
||||||
|
// All allocated VaapiPictures, regardless of their current state. Pictures
|
||||||
|
// are allocated at AssignPictureBuffers() and are kept until dtor or
|
||||||
|
// TryFinishSurfaceSetChange(). Comes after |vaapi_wrapper_| to ensure all
|
||||||
|
// pictures are destroyed before this is destroyed.
|
||||||
|
base::small_map<std::map<int32_t, std::unique_ptr<VaapiPicture>>> pictures_
|
||||||
|
GUARDED_BY(lock_);
|
||||||
|
// List of PictureBuffer ids available to be sent to |client_| via
|
||||||
|
// OutputPicture() (|client_| returns them via ReusePictureBuffer()).
|
||||||
|
std::list<int32_t> available_picture_buffers_ GUARDED_BY(lock_);
|
||||||
|
|
||||||
|
// VASurfaces available and that can be passed to |decoder_| for its use upon
|
||||||
|
// CreateSurface() request (and then returned via RecycleVASurface()).
|
||||||
|
std::list<std::unique_ptr<ScopedVASurfaceID>> available_va_surfaces_
|
||||||
|
GUARDED_BY(lock_);
|
||||||
|
// Signalled when output surfaces are queued into |available_va_surfaces_|.
|
||||||
|
base::ConditionVariable surfaces_available_;
|
||||||
|
// VASurfaceIDs format, filled in when created.
|
||||||
|
unsigned int va_surface_format_;
|
||||||
|
|
||||||
|
// Pending output requests from the decoder. When it indicates that we should
|
||||||
|
// output a surface and we have an available Picture (i.e. texture) ready
|
||||||
|
// to use, we'll execute the callback passing the Picture. The callback
|
||||||
|
// will put the contents of the surface into the picture and return it to
|
||||||
|
// the client, releasing the surface as well.
|
||||||
|
// If we don't have any available |pictures_| at the time when the decoder
|
||||||
|
// requests output, we'll store the request in this queue for later and run it
|
||||||
|
// once the client gives us more textures via ReusePictureBuffer().
|
||||||
|
// Only used on |task_runner_|.
|
||||||
|
base::queue<base::OnceClosure> pending_output_cbs_;
|
||||||
|
|
||||||
|
// WeakPtr<> pointing to |this| for use in posting tasks from the decoder
|
||||||
|
// thread back to the ChildThread. Because the decoder thread is a member of
|
||||||
|
// this class, any task running on the decoder thread is guaranteed that this
|
||||||
|
// object is still alive. As a result, tasks posted from ChildThread to
|
||||||
|
// decoder thread should use base::Unretained(this), and tasks posted from the
|
||||||
|
// decoder thread to the ChildThread should use |weak_this_|.
|
||||||
|
base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_;
|
||||||
|
|
||||||
|
// Callback used to recycle VASurfaces. Only used on |task_runner_|.
|
||||||
|
base::RepeatingCallback<void(std::unique_ptr<ScopedVASurfaceID>, VASurfaceID)>
|
||||||
|
va_surface_recycle_cb_;
|
||||||
|
|
||||||
|
// To expose client callbacks from VideoDecodeAccelerator. Used only on
|
||||||
|
// |task_runner_|.
|
||||||
|
std::unique_ptr<base::WeakPtrFactory<Client>> client_ptr_factory_;
|
||||||
|
base::WeakPtr<Client> client_;
|
||||||
|
|
||||||
|
// ChildThread's task runner.
|
||||||
|
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||||
|
|
||||||
|
base::Thread decoder_thread_;
|
||||||
|
// Use this to post tasks to |decoder_thread_| instead of
|
||||||
|
// |decoder_thread_.task_runner()| because the latter will be NULL once
|
||||||
|
// |decoder_thread_.Stop()| returns.
|
||||||
|
scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_;
|
||||||
|
|
||||||
|
// Whether we are waiting for any |pending_output_cbs_| to be run before
|
||||||
|
// NotifyingFlushDone. Only used on |task_runner_|.
|
||||||
|
bool finish_flush_pending_;
|
||||||
|
|
||||||
|
// Decoder requested a new surface set and we are waiting for all the surfaces
|
||||||
|
// to be returned before we can free them. Only used on |task_runner_|.
|
||||||
|
bool awaiting_va_surfaces_recycle_;
|
||||||
|
|
||||||
|
// Last requested number/resolution/visible rectangle of output
|
||||||
|
// PictureBuffers.
|
||||||
|
size_t requested_num_pics_;
|
||||||
|
gfx::Size requested_pic_size_;
|
||||||
|
gfx::Rect requested_visible_rect_;
|
||||||
|
// Potential extra PictureBuffers to request, used only on
|
||||||
|
// BufferAllocationMode::kNone, see DecideBufferAllocationMode().
|
||||||
|
size_t num_extra_pics_ = 0;
|
||||||
|
|
||||||
|
// Max number of reference frames needed by |decoder_|. Only used on
|
||||||
|
// |task_runner_| and when in BufferAllocationMode::kNone.
|
||||||
|
size_t requested_num_reference_frames_;
|
||||||
|
size_t previously_requested_num_reference_frames_;
|
||||||
|
|
||||||
|
// The video stream's profile.
|
||||||
|
VideoCodecProfile profile_;
|
||||||
|
|
||||||
|
// Callback to make GL context current.
|
||||||
|
MakeGLContextCurrentCallback make_context_current_cb_;
|
||||||
|
|
||||||
|
// Callback to bind a GLImage to a given texture.
|
||||||
|
BindGLImageCallback bind_image_cb_;
|
||||||
|
|
||||||
|
// The WeakPtrFactory for |weak_this_|.
|
||||||
|
base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
|
||||||
|
#endif // MEDIA_GPU_VAAPI_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
|
3308
media/gpu/vaapi/vaapi_wrapper.cc
Normal file
627
media/gpu/vaapi/vaapi_wrapper.h
Normal file
|
@ -0,0 +1,627 @@
|
||||||
|
// Copyright 2013 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// This file contains an implementation of VaapiWrapper, used by
|
||||||
|
// VaapiVideoDecodeAccelerator and VaapiH264Decoder for decode,
|
||||||
|
// and VaapiVideoEncodeAccelerator for encode, to interface
|
||||||
|
// with libva (VA-API library for hardware video codec).
|
||||||
|
|
||||||
|
#ifndef MEDIA_GPU_VAAPI_VAAPI_WRAPPER_H_
|
||||||
|
#define MEDIA_GPU_VAAPI_VAAPI_WRAPPER_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <va/va.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/files/file.h"
|
||||||
|
#include "base/gtest_prod_util.h"
|
||||||
|
#include "base/macros.h"
|
||||||
|
#include "base/memory/ref_counted.h"
|
||||||
|
#include "base/memory/scoped_refptr.h"
|
||||||
|
#include "base/synchronization/lock.h"
|
||||||
|
#include "base/thread_annotations.h"
|
||||||
|
#include "build/chromeos_buildflags.h"
|
||||||
|
#include "media/gpu/chromeos/fourcc.h"
|
||||||
|
#include "media/gpu/media_gpu_export.h"
|
||||||
|
#include "media/gpu/vaapi/va_surface.h"
|
||||||
|
#include "media/gpu/vaapi/vaapi_utils.h"
|
||||||
|
#include "media/video/video_decode_accelerator.h"
|
||||||
|
#include "media/video/video_encode_accelerator.h"
|
||||||
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||||
|
#include "ui/gfx/geometry/size.h"
|
||||||
|
|
||||||
|
#if BUILDFLAG(USE_VAAPI_X11)
|
||||||
|
#include "ui/gfx/x/xproto.h" // nogncheck
|
||||||
|
#endif // BUILDFLAG(USE_VAAPI_X11)
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
enum class BufferFormat;
|
||||||
|
class NativePixmap;
|
||||||
|
class NativePixmapDmaBuf;
|
||||||
|
class Rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace media {
|
||||||
|
constexpr unsigned int kInvalidVaRtFormat = 0u;
|
||||||
|
|
||||||
|
class VideoFrame;
|
||||||
|
|
||||||
|
// Enum, function and callback type to allow VaapiWrapper to log errors in VA
|
||||||
|
// function calls executed on behalf of its owner. |histogram_name| is prebound
|
||||||
|
// to allow for disinguishing such owners.
|
||||||
|
enum class VaapiFunctions;
|
||||||
|
void ReportVaapiErrorToUMA(const std::string& histogram_name,
|
||||||
|
VaapiFunctions value);
|
||||||
|
using ReportErrorToUMACB = base::RepeatingCallback<void(VaapiFunctions)>;
|
||||||
|
|
||||||
|
// This struct holds a NativePixmapDmaBuf, usually the result of exporting a VA
|
||||||
|
// surface, and some associated size information needed to tell clients about
|
||||||
|
// the underlying buffer.
|
||||||
|
struct NativePixmapAndSizeInfo {
|
||||||
|
NativePixmapAndSizeInfo();
|
||||||
|
~NativePixmapAndSizeInfo();
|
||||||
|
|
||||||
|
// The VA-API internal buffer dimensions, which may be different than the
|
||||||
|
// dimensions requested at the time of creation of the surface (but always
|
||||||
|
// larger than or equal to those). This can be used for validation in, e.g.,
|
||||||
|
// testing.
|
||||||
|
gfx::Size va_surface_resolution;
|
||||||
|
|
||||||
|
// The size of the underlying Buffer Object. A use case for this is when an
|
||||||
|
// image decode is requested and the caller needs to know the size of the
|
||||||
|
// allocated buffer for caching purposes.
|
||||||
|
size_t byte_size = 0u;
|
||||||
|
|
||||||
|
// Contains the information needed to use the surface in a graphics API,
|
||||||
|
// including the visible size (|pixmap|->GetBufferSize()) which should be no
|
||||||
|
// larger than |va_surface_resolution|.
|
||||||
|
scoped_refptr<gfx::NativePixmapDmaBuf> pixmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class VAImplementation {
|
||||||
|
kMesaGallium,
|
||||||
|
kIntelI965,
|
||||||
|
kIntelIHD,
|
||||||
|
kNVIDIAVDPAU,
|
||||||
|
kOther,
|
||||||
|
kInvalid,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class handles VA-API calls and ensures proper locking of VA-API calls
|
||||||
|
// to libva, the userspace shim to the HW codec driver. libva is not
|
||||||
|
// thread-safe, so we have to perform locking ourselves. This class is fully
|
||||||
|
// synchronous and its constructor, all of its methods, and its destructor must
|
||||||
|
// be called on the same sequence. These methods may wait on the |va_lock_|
|
||||||
|
// which guards libva calls across all VaapiWrapper instances and other libva
|
||||||
|
// call sites.
|
||||||
|
//
|
||||||
|
// This class is responsible for managing VAAPI connection, contexts and state.
|
||||||
|
// It is also responsible for managing and freeing VABuffers (not VASurfaces),
|
||||||
|
// which are used to queue parameters and slice data to the HW codec,
|
||||||
|
// as well as underlying memory for VASurfaces themselves.
|
||||||
|
class MEDIA_GPU_EXPORT VaapiWrapper
|
||||||
|
: public base::RefCountedThreadSafe<VaapiWrapper> {
|
||||||
|
public:
|
||||||
|
enum CodecMode {
|
||||||
|
kDecode,
|
||||||
|
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
// NOTE: A kDecodeProtected VaapiWrapper is created using the actual video
|
||||||
|
// profile and an extra VAProfileProtected, each with some special added
|
||||||
|
// VAConfigAttribs. Then when CreateProtectedSession() is called, it will
|
||||||
|
// then create a protected session using protected profile & entrypoint
|
||||||
|
// which gets attached to the decoding context (or attached when the
|
||||||
|
// decoding context is created or re-created). This then enables
|
||||||
|
// decrypt + decode support in the driver and encrypted frame data can then
|
||||||
|
// be submitted.
|
||||||
|
kDecodeProtected, // Decrypt + decode to protected surface.
|
||||||
|
#endif
|
||||||
|
kEncodeConstantBitrate, // Encode with Constant Bitrate algorithm.
|
||||||
|
kEncodeConstantQuantizationParameter, // Encode with Constant Quantization
|
||||||
|
// Parameter algorithm.
|
||||||
|
kVideoProcess,
|
||||||
|
kCodecModeMax,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is enum associated with VASurfaceAttribUsageHint.
|
||||||
|
enum class SurfaceUsageHint : int32_t {
|
||||||
|
kGeneric = VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC,
|
||||||
|
kVideoDecoder = VA_SURFACE_ATTRIB_USAGE_HINT_DECODER,
|
||||||
|
kVideoEncoder = VA_SURFACE_ATTRIB_USAGE_HINT_ENCODER,
|
||||||
|
kVideoProcessWrite = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_WRITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
using InternalFormats = struct {
|
||||||
|
bool yuv420 : 1;
|
||||||
|
bool yuv420_10 : 1;
|
||||||
|
bool yuv422 : 1;
|
||||||
|
bool yuv444 : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the type of the underlying VA-API implementation.
|
||||||
|
static VAImplementation GetImplementationType();
|
||||||
|
|
||||||
|
// Return an instance of VaapiWrapper initialized for |va_profile| and
|
||||||
|
// |mode|. |report_error_to_uma_cb| will be called independently from
|
||||||
|
// reporting errors to clients via method return values.
|
||||||
|
static scoped_refptr<VaapiWrapper> Create(
|
||||||
|
CodecMode mode,
|
||||||
|
VAProfile va_profile,
|
||||||
|
EncryptionScheme encryption_scheme,
|
||||||
|
const ReportErrorToUMACB& report_error_to_uma_cb);
|
||||||
|
|
||||||
|
// Create VaapiWrapper for VideoCodecProfile. It maps VideoCodecProfile
|
||||||
|
// |profile| to VAProfile.
|
||||||
|
// |report_error_to_uma_cb| will be called independently from reporting
|
||||||
|
// errors to clients via method return values.
|
||||||
|
static scoped_refptr<VaapiWrapper> CreateForVideoCodec(
|
||||||
|
CodecMode mode,
|
||||||
|
VideoCodecProfile profile,
|
||||||
|
EncryptionScheme encryption_scheme,
|
||||||
|
const ReportErrorToUMACB& report_error_to_uma_cb);
|
||||||
|
|
||||||
|
VaapiWrapper(const VaapiWrapper&) = delete;
|
||||||
|
VaapiWrapper& operator=(const VaapiWrapper&) = delete;
|
||||||
|
|
||||||
|
// Returns the supported SVC scalability modes for specified profile.
|
||||||
|
static std::vector<SVCScalabilityMode> GetSupportedScalabilityModes(
|
||||||
|
VideoCodecProfile media_profile,
|
||||||
|
VAProfile va_profile);
|
||||||
|
|
||||||
|
// Return the supported video encode profiles.
|
||||||
|
static VideoEncodeAccelerator::SupportedProfiles GetSupportedEncodeProfiles();
|
||||||
|
|
||||||
|
// Return the supported video decode profiles.
|
||||||
|
static VideoDecodeAccelerator::SupportedProfiles GetSupportedDecodeProfiles();
|
||||||
|
|
||||||
|
// Return true when decoding using |va_profile| is supported.
|
||||||
|
static bool IsDecodeSupported(VAProfile va_profile);
|
||||||
|
|
||||||
|
// Returns the supported internal formats for decoding using |va_profile|. If
|
||||||
|
// decoding is not supported for that profile, returns InternalFormats{}.
|
||||||
|
static InternalFormats GetDecodeSupportedInternalFormats(
|
||||||
|
VAProfile va_profile);
|
||||||
|
|
||||||
|
// Returns true if |rt_format| is supported for decoding using |va_profile|.
|
||||||
|
// Returns false if |rt_format| or |va_profile| is not supported for decoding.
|
||||||
|
static bool IsDecodingSupportedForInternalFormat(VAProfile va_profile,
|
||||||
|
unsigned int rt_format);
|
||||||
|
|
||||||
|
// Gets the minimum surface size allowed for decoding using |va_profile|.
|
||||||
|
// Returns true if the size can be obtained, false otherwise. The minimum
|
||||||
|
// dimension (width or height) returned is 1. Particularly, if a dimension is
|
||||||
|
// not reported by the driver, the dimension is returned as 1.
|
||||||
|
static bool GetDecodeMinResolution(VAProfile va_profile, gfx::Size* min_size);
|
||||||
|
|
||||||
|
// Gets the maximum surface size allowed for decoding using |va_profile|.
|
||||||
|
// Returns true if the size can be obtained, false otherwise. Because of the
|
||||||
|
// initialization in VASupportedProfiles::FillProfileInfo_Locked(), the size
|
||||||
|
// is guaranteed to not be empty (as long as this method returns true).
|
||||||
|
static bool GetDecodeMaxResolution(VAProfile va_profile, gfx::Size* max_size);
|
||||||
|
|
||||||
|
// Obtains a suitable FOURCC that can be used in vaCreateImage() +
|
||||||
|
// vaGetImage(). |rt_format| corresponds to the JPEG's subsampling format.
|
||||||
|
// |preferred_fourcc| is the FOURCC of the format preferred by the caller. If
|
||||||
|
// it is determined that the VAAPI driver can do the conversion from the
|
||||||
|
// internal format (|rt_format|), *|suitable_fourcc| is set to
|
||||||
|
// |preferred_fourcc|. Otherwise, it is set to a supported format. Returns
|
||||||
|
// true if a suitable FOURCC could be determined, false otherwise (e.g., if
|
||||||
|
// the |rt_format| is unsupported by the driver). If |preferred_fourcc| is not
|
||||||
|
// a supported image format, *|suitable_fourcc| is set to VA_FOURCC_I420.
|
||||||
|
static bool GetJpegDecodeSuitableImageFourCC(unsigned int rt_format,
|
||||||
|
uint32_t preferred_fourcc,
|
||||||
|
uint32_t* suitable_fourcc);
|
||||||
|
// Checks to see if VAProfileNone is supported on this decoder
|
||||||
|
static bool IsVppProfileSupported();
|
||||||
|
|
||||||
|
// Checks the surface size is allowed for VPP. Returns true if the size is
|
||||||
|
// supported, false otherwise.
|
||||||
|
static bool IsVppResolutionAllowed(const gfx::Size& size);
|
||||||
|
|
||||||
|
// Returns true if the VPP supports converting from/to |fourcc|.
|
||||||
|
static bool IsVppFormatSupported(uint32_t fourcc);
|
||||||
|
|
||||||
|
// Returns the pixel formats supported by the VPP.
|
||||||
|
static std::vector<Fourcc> GetVppSupportedFormats();
|
||||||
|
|
||||||
|
// Returns true if VPP supports the format conversion from a JPEG decoded
|
||||||
|
// internal surface to a FOURCC. |rt_format| corresponds to the JPEG's
|
||||||
|
// subsampling format. |fourcc| is the output surface's FOURCC.
|
||||||
|
static bool IsVppSupportedForJpegDecodedSurfaceToFourCC(
|
||||||
|
unsigned int rt_format,
|
||||||
|
uint32_t fourcc);
|
||||||
|
|
||||||
|
// Return true when JPEG encode is supported.
|
||||||
|
static bool IsJpegEncodeSupported();
|
||||||
|
|
||||||
|
// Return true when the specified image format is supported.
|
||||||
|
static bool IsImageFormatSupported(const VAImageFormat& format);
|
||||||
|
|
||||||
|
// Returns the list of VAImageFormats supported by the driver.
|
||||||
|
static const std::vector<VAImageFormat>& GetSupportedImageFormatsForTesting();
|
||||||
|
|
||||||
|
// Returns the list of supported profiles and entrypoints for a given |mode|.
|
||||||
|
static std::map<VAProfile, std::vector<VAEntrypoint>>
|
||||||
|
GetSupportedConfigurationsForCodecModeForTesting(CodecMode mode);
|
||||||
|
|
||||||
|
static VAEntrypoint GetDefaultVaEntryPoint(CodecMode mode, VAProfile profile);
|
||||||
|
|
||||||
|
static uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt);
|
||||||
|
|
||||||
|
// Creates |num_surfaces| VASurfaceIDs of |va_format|, |size| and
|
||||||
|
// |surface_usage_hints| and, if successful, creates a |va_context_id_| of the
|
||||||
|
// same size. |surface_usage_hints| may affect an alignment and tiling of the
|
||||||
|
// created surface. Returns true if successful, with the created IDs in
|
||||||
|
// |va_surfaces|. The client is responsible for destroying |va_surfaces| via
|
||||||
|
// DestroyContextAndSurfaces() to free the allocated surfaces.
|
||||||
|
virtual bool CreateContextAndSurfaces(
|
||||||
|
unsigned int va_format,
|
||||||
|
const gfx::Size& size,
|
||||||
|
const std::vector<SurfaceUsageHint>& surface_usage_hints,
|
||||||
|
size_t num_surfaces,
|
||||||
|
std::vector<VASurfaceID>* va_surfaces) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Creates |num_surfaces| ScopedVASurfaces of |va_format| and |size| and, if
|
||||||
|
// successful, creates a |va_context_id_| of the same size. Returns an empty
|
||||||
|
// vector if creation failed. If |visible_size| is supplied, the returned
|
||||||
|
// ScopedVASurface's size is set to it. Otherwise, it's set to |size| (refer
|
||||||
|
// to CreateScopedVASurfaces() for details).
|
||||||
|
virtual std::vector<std::unique_ptr<ScopedVASurface>>
|
||||||
|
CreateContextAndScopedVASurfaces(
|
||||||
|
unsigned int va_format,
|
||||||
|
const gfx::Size& size,
|
||||||
|
const std::vector<SurfaceUsageHint>& usage_hints,
|
||||||
|
size_t num_surfaces,
|
||||||
|
const absl::optional<gfx::Size>& visible_size);
|
||||||
|
|
||||||
|
// Attempts to create a protected session that will be attached to the
|
||||||
|
// decoding context to enable encrypted video decoding. If it cannot be
|
||||||
|
// attached now, it will be attached when the decoding context is created or
|
||||||
|
// re-created. |encryption| should be the encryption scheme from the
|
||||||
|
// DecryptConfig. |hw_config| should have been obtained from the OEMCrypto
|
||||||
|
// implementation via the CdmFactoryDaemonProxy. |hw_identifier_out| is an
|
||||||
|
// output parameter which will return session specific information which can
|
||||||
|
// be passed through the ChromeOsCdmContext to retrieve encrypted key
|
||||||
|
// information. Returns true on success and false otherwise.
|
||||||
|
bool CreateProtectedSession(media::EncryptionScheme encryption,
|
||||||
|
const std::vector<uint8_t>& hw_config,
|
||||||
|
std::vector<uint8_t>* hw_identifier_out);
|
||||||
|
// Returns true if and only if we have created a protected session and
|
||||||
|
// querying libva indicates that our protected session is no longer alive,
|
||||||
|
// otherwise this will return false.
|
||||||
|
bool IsProtectedSessionDead();
|
||||||
|
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
// Returns true if and only if |va_protected_session_id| is not VA_INVALID_ID
|
||||||
|
// and querying libva indicates that the protected session identified by
|
||||||
|
// |va_protected_session_id| is no longer alive.
|
||||||
|
bool IsProtectedSessionDead(VAProtectedSessionID va_protected_session_id);
|
||||||
|
|
||||||
|
// Returns the ID of the current protected session or VA_INVALID_ID if there's
|
||||||
|
// none. This must be called on the same sequence as other methods that use
|
||||||
|
// the protected session ID internally.
|
||||||
|
//
|
||||||
|
// TODO(b/183515581): update this documentation once we force the VaapiWrapper
|
||||||
|
// to be used on a single sequence.
|
||||||
|
VAProtectedSessionID GetProtectedSessionID() const;
|
||||||
|
#endif
|
||||||
|
// If we have a protected session, destroys it immediately. This should be
|
||||||
|
// used as part of recovering dead protected sessions.
|
||||||
|
void DestroyProtectedSession();
|
||||||
|
|
||||||
|
// Releases the |va_surfaces| and destroys |va_context_id_|.
|
||||||
|
void DestroyContextAndSurfaces(std::vector<VASurfaceID> va_surfaces);
|
||||||
|
|
||||||
|
// Creates a VAContextID of |size| (unless it's a Vpp context in which case
|
||||||
|
// |size| is ignored and 0x0 is used instead). The client is responsible for
|
||||||
|
// releasing said context via DestroyContext() or DestroyContextAndSurfaces(),
|
||||||
|
// or it will be released on dtor. If a valid |va_protected_session_id_|
|
||||||
|
// exists, it will be attached to the newly created |va_context_id_| as well.
|
||||||
|
virtual bool CreateContext(const gfx::Size& size) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Destroys the context identified by |va_context_id_|.
|
||||||
|
virtual void DestroyContext();
|
||||||
|
|
||||||
|
// Requests |num_surfaces| ScopedVASurfaces of size |size|, |va_rt_format| and
|
||||||
|
// optionally |va_fourcc|. Returns self-cleaning ScopedVASurfaces or empty
|
||||||
|
// vector if creation failed. If |visible_size| is supplied, the returned
|
||||||
|
// ScopedVASurfaces' size are set to it: for example, we may want to request a
|
||||||
|
// 16x16 surface to decode a 13x12 JPEG: we may want to keep track of the
|
||||||
|
// visible size 13x12 inside the ScopedVASurface to inform the surface's users
|
||||||
|
// that that's the only region with meaningful content. If |visible_size| is
|
||||||
|
// not supplied, we store |size| in the returned ScopedVASurfaces.
|
||||||
|
virtual std::vector<std::unique_ptr<ScopedVASurface>> CreateScopedVASurfaces(
|
||||||
|
unsigned int va_rt_format,
|
||||||
|
const gfx::Size& size,
|
||||||
|
const std::vector<SurfaceUsageHint>& usage_hints,
|
||||||
|
size_t num_surfaces,
|
||||||
|
const absl::optional<gfx::Size>& visible_size,
|
||||||
|
const absl::optional<uint32_t>& va_fourcc);
|
||||||
|
|
||||||
|
// Creates a self-releasing VASurface from |pixmap|. The created VASurface
|
||||||
|
// shares the ownership of the underlying buffer represented by |pixmap|. The
|
||||||
|
// ownership of the surface is transferred to the caller. A caller can destroy
|
||||||
|
// |pixmap| after this method returns and the underlying buffer will be kept
|
||||||
|
// alive by the VASurface. |protected_content| should only be true if the
|
||||||
|
// format needs VA_RT_FORMAT_PROTECTED (currently only true for AMD).
|
||||||
|
virtual scoped_refptr<VASurface> CreateVASurfaceForPixmap(
|
||||||
|
scoped_refptr<gfx::NativePixmap> pixmap,
|
||||||
|
bool protected_content = false);
|
||||||
|
|
||||||
|
// Creates a self-releasing VASurface from |buffers|. The ownership of the
|
||||||
|
// surface is transferred to the caller. |buffers| should be a pointer array
|
||||||
|
// of size 1, with |buffer_size| corresponding to its size. |size| should be
|
||||||
|
// the desired surface dimensions (which does not need to map to |buffer_size|
|
||||||
|
// in any relevant way). |buffers| should be kept alive when using the
|
||||||
|
// VASurface and for accessing the data after the operation is complete.
|
||||||
|
scoped_refptr<VASurface> CreateVASurfaceForUserPtr(const gfx::Size& size,
|
||||||
|
uintptr_t* buffers,
|
||||||
|
size_t buffer_size);
|
||||||
|
|
||||||
|
// Syncs and exports |va_surface| as a gfx::NativePixmapDmaBuf. Currently, the
|
||||||
|
// only VAAPI surface pixel formats supported are VA_FOURCC_IMC3 and
|
||||||
|
// VA_FOURCC_NV12.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// - For VA_FOURCC_IMC3, the format of the returned NativePixmapDmaBuf is
|
||||||
|
// gfx::BufferFormat::YVU_420 because we don't have a YUV_420 format. The
|
||||||
|
// planes are flipped accordingly, i.e.,
|
||||||
|
// gfx::NativePixmapDmaBuf::GetDmaBufOffset(1) refers to the V plane.
|
||||||
|
// TODO(andrescj): revisit once crrev.com/c/1573718 lands.
|
||||||
|
//
|
||||||
|
// - For VA_FOURCC_NV12, the format of the returned NativePixmapDmaBuf is
|
||||||
|
// gfx::BufferFormat::YUV_420_BIPLANAR.
|
||||||
|
//
|
||||||
|
// Returns nullptr on failure.
|
||||||
|
std::unique_ptr<NativePixmapAndSizeInfo> ExportVASurfaceAsNativePixmapDmaBuf(
|
||||||
|
const ScopedVASurface& va_surface);
|
||||||
|
|
||||||
|
// Synchronize the VASurface explicitly. This is useful when sharing a surface
|
||||||
|
// between contexts.
|
||||||
|
bool SyncSurface(VASurfaceID va_surface_id) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Calls SubmitBuffer_Locked() to request libva to allocate a new VABufferID
|
||||||
|
// of |va_buffer_type| and |size|, and to map-and-copy the |data| into it. The
|
||||||
|
// allocated VABufferIDs stay alive until DestroyPendingBuffers_Locked(). Note
|
||||||
|
// that this method does not submit the buffers for execution, they are simply
|
||||||
|
// stored until ExecuteAndDestroyPendingBuffers()/Execute_Locked(). The
|
||||||
|
// ownership of |data| stays with the caller. On failure, all pending buffers
|
||||||
|
// are destroyed.
|
||||||
|
bool SubmitBuffer(VABufferType va_buffer_type,
|
||||||
|
size_t size,
|
||||||
|
const void* data) WARN_UNUSED_RESULT;
|
||||||
|
// Convenient templatized version of SubmitBuffer() where |size| is deduced to
|
||||||
|
// be the size of the type of |*data|.
|
||||||
|
template <typename T>
|
||||||
|
bool WARN_UNUSED_RESULT SubmitBuffer(VABufferType va_buffer_type,
|
||||||
|
const T* data) {
|
||||||
|
CHECK(sequence_checker_.CalledOnValidSequence());
|
||||||
|
return SubmitBuffer(va_buffer_type, sizeof(T), data);
|
||||||
|
}
|
||||||
|
// Batch-version of SubmitBuffer(), where the lock for accessing libva is
|
||||||
|
// acquired only once.
|
||||||
|
struct VABufferDescriptor {
|
||||||
|
VABufferType type;
|
||||||
|
size_t size;
|
||||||
|
const void* data;
|
||||||
|
};
|
||||||
|
bool SubmitBuffers(const std::vector<VABufferDescriptor>& va_buffers)
|
||||||
|
WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Destroys all |pending_va_buffers_| sent via SubmitBuffer*(). Useful when a
|
||||||
|
// pending job is to be cancelled (on reset or error).
|
||||||
|
void DestroyPendingBuffers();
|
||||||
|
|
||||||
|
// Executes job in hardware on target |va_surface_id| and destroys pending
|
||||||
|
// buffers. Returns false if Execute() fails.
|
||||||
|
virtual bool ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id)
|
||||||
|
WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Maps each |va_buffers| ID and copies the data described by the associated
|
||||||
|
// VABufferDescriptor into it; then calls Execute_Locked() on |va_surface_id|.
|
||||||
|
bool MapAndCopyAndExecute(
|
||||||
|
VASurfaceID va_surface_id,
|
||||||
|
const std::vector<std::pair<VABufferID, VABufferDescriptor>>& va_buffers)
|
||||||
|
WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
#if BUILDFLAG(USE_VAAPI_X11)
|
||||||
|
// Put data from |va_surface_id| into |x_pixmap| of size
|
||||||
|
// |dest_size|, converting/scaling to it.
|
||||||
|
bool PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
|
||||||
|
x11::Pixmap x_pixmap,
|
||||||
|
gfx::Size dest_size) WARN_UNUSED_RESULT;
|
||||||
|
#endif // BUILDFLAG(USE_VAAPI_X11)
|
||||||
|
|
||||||
|
// Creates a ScopedVAImage from a VASurface |va_surface_id| and map it into
|
||||||
|
// memory with the given |format| and |size|. If |format| is not equal to the
|
||||||
|
// internal format, the underlying implementation will do format conversion if
|
||||||
|
// supported. |size| should be smaller than or equal to the surface. If |size|
|
||||||
|
// is smaller, the image will be cropped.
|
||||||
|
std::unique_ptr<ScopedVAImage> CreateVaImage(VASurfaceID va_surface_id,
|
||||||
|
VAImageFormat* format,
|
||||||
|
const gfx::Size& size);
|
||||||
|
|
||||||
|
// Uploads contents of |frame| into |va_surface_id| for encode.
|
||||||
|
virtual bool UploadVideoFrameToSurface(const VideoFrame& frame,
|
||||||
|
VASurfaceID va_surface_id,
|
||||||
|
const gfx::Size& va_surface_size)
|
||||||
|
WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Creates a buffer of |size| bytes to be used as encode output.
|
||||||
|
virtual std::unique_ptr<ScopedVABuffer> CreateVABuffer(VABufferType type,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
// Gets the encoded frame linear size of the buffer with given |buffer_id|.
|
||||||
|
// |sync_surface_id| will be used as a sync point, i.e. it will have to become
|
||||||
|
// idle before starting the acquirement. |sync_surface_id| should be the
|
||||||
|
// source surface passed to the encode job. Returns 0 if it fails for any
|
||||||
|
// reason.
|
||||||
|
virtual uint64_t GetEncodedChunkSize(VABufferID buffer_id,
|
||||||
|
VASurfaceID sync_surface_id)
|
||||||
|
WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Downloads the contents of the buffer with given |buffer_id| into a buffer
|
||||||
|
// of size |target_size|, pointed to by |target_ptr|. The number of bytes
|
||||||
|
// downloaded will be returned in |coded_data_size|. |sync_surface_id| will
|
||||||
|
// be used as a sync point, i.e. it will have to become idle before starting
|
||||||
|
// the download. |sync_surface_id| should be the source surface passed
|
||||||
|
// to the encode job. Returns false if it fails for any reason. For example,
|
||||||
|
// the linear size of the resulted encoded frame is larger than |target_size|.
|
||||||
|
virtual bool DownloadFromVABuffer(VABufferID buffer_id,
|
||||||
|
VASurfaceID sync_surface_id,
|
||||||
|
uint8_t* target_ptr,
|
||||||
|
size_t target_size,
|
||||||
|
size_t* coded_data_size) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Get the max number of reference frames for encoding supported by the
|
||||||
|
// driver.
|
||||||
|
// For H.264 encoding, the value represents the maximum number of reference
|
||||||
|
// frames for both the reference picture list 0 (bottom 16 bits) and the
|
||||||
|
// reference picture list 1 (top 16 bits).
|
||||||
|
virtual bool GetVAEncMaxNumOfRefFrames(VideoCodecProfile profile,
|
||||||
|
size_t* max_ref_frames)
|
||||||
|
WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Gets packed headers are supported for encoding. This is called for
|
||||||
|
// H264 encoding. |packed_sps|, |packed_pps| and |packed_slice| stands for
|
||||||
|
// whether packed slice parameter set, packed picture parameter set and packed
|
||||||
|
// slice header is supported, respectively.
|
||||||
|
virtual bool GetSupportedPackedHeaders(VideoCodecProfile profile,
|
||||||
|
bool& packed_sps,
|
||||||
|
bool& packed_pps,
|
||||||
|
bool& packed_slice) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Checks if the driver supports frame rotation.
|
||||||
|
bool IsRotationSupported();
|
||||||
|
|
||||||
|
// Blits a VASurface |va_surface_src| into another VASurface
|
||||||
|
// |va_surface_dest| applying pixel format conversion, rotation, cropping
|
||||||
|
// and scaling if needed. |src_rect| and |dest_rect| are optional. They can
|
||||||
|
// be used to specify the area used in the blit. If |va_protected_session_id|
|
||||||
|
// is provided and is not VA_INVALID_ID, the corresponding protected session
|
||||||
|
// is attached to the VPP context prior to submitting the VPP buffers and
|
||||||
|
// detached after submitting those buffers.
|
||||||
|
virtual bool BlitSurface(
|
||||||
|
const VASurface& va_surface_src,
|
||||||
|
const VASurface& va_surface_dest,
|
||||||
|
absl::optional<gfx::Rect> src_rect = absl::nullopt,
|
||||||
|
absl::optional<gfx::Rect> dest_rect = absl::nullopt,
|
||||||
|
VideoRotation rotation = VIDEO_ROTATION_0
|
||||||
|
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
,
|
||||||
|
VAProtectedSessionID va_protected_session_id = VA_INVALID_ID
|
||||||
|
#endif
|
||||||
|
) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Initialize static data before sandbox is enabled.
|
||||||
|
static void PreSandboxInitialization();
|
||||||
|
|
||||||
|
// vaDestroySurfaces() a vector or a single VASurfaceID.
|
||||||
|
virtual void DestroySurfaces(std::vector<VASurfaceID> va_surfaces);
|
||||||
|
virtual void DestroySurface(VASurfaceID va_surface_id);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
VaapiWrapper(CodecMode mode);
|
||||||
|
virtual ~VaapiWrapper();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class base::RefCountedThreadSafe<VaapiWrapper>;
|
||||||
|
friend class VaapiWrapperTest;
|
||||||
|
friend class VaapiVideoEncodeAcceleratorTest;
|
||||||
|
|
||||||
|
FRIEND_TEST_ALL_PREFIXES(VaapiTest, LowQualityEncodingSetting);
|
||||||
|
FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, ScopedVAImage);
|
||||||
|
FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVAImage);
|
||||||
|
FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVABufferMapping);
|
||||||
|
FRIEND_TEST_ALL_PREFIXES(VaapiMinigbmTest, AllocateAndCompareWithMinigbm);
|
||||||
|
|
||||||
|
bool Initialize(VAProfile va_profile,
|
||||||
|
EncryptionScheme encryption_scheme) WARN_UNUSED_RESULT;
|
||||||
|
void Deinitialize();
|
||||||
|
bool VaInitialize(const ReportErrorToUMACB& report_error_to_uma_cb)
|
||||||
|
WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Tries to allocate |num_surfaces| VASurfaceIDs of |size| and |va_format|.
|
||||||
|
// Fills |va_surfaces| and returns true if successful, or returns false.
|
||||||
|
bool CreateSurfaces(unsigned int va_format,
|
||||||
|
const gfx::Size& size,
|
||||||
|
const std::vector<SurfaceUsageHint>& usage_hints,
|
||||||
|
size_t num_surfaces,
|
||||||
|
std::vector<VASurfaceID>* va_surfaces) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Carries out the vaBeginPicture()-vaRenderPicture()-vaEndPicture() on target
|
||||||
|
// |va_surface_id|. Returns false if any of these calls fails.
|
||||||
|
bool Execute_Locked(VASurfaceID va_surface_id,
|
||||||
|
const std::vector<VABufferID>& va_buffers)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(va_lock_) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
virtual void DestroyPendingBuffers_Locked()
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
|
||||||
|
|
||||||
|
// Requests libva to allocate a new VABufferID of type |va_buffer.type|, then
|
||||||
|
// maps-and-copies |va_buffer.size| contents of |va_buffer.data| to it. If a
|
||||||
|
// failure occurs, calls DestroyPendingBuffers_Locked() and returns false.
|
||||||
|
virtual bool SubmitBuffer_Locked(const VABufferDescriptor& va_buffer)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(va_lock_) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Maps |va_buffer_id| and, if successful, copies the contents of |va_buffer|
|
||||||
|
// into it.
|
||||||
|
bool MapAndCopy_Locked(VABufferID va_buffer_id,
|
||||||
|
const VABufferDescriptor& va_buffer)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(va_lock_) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
// Queries whether |va_profile_| and |va_entrypoint_| support encoding quality
|
||||||
|
// setting and, if available, configures it to its maximum value, for lower
|
||||||
|
// consumption and maximum speed.
|
||||||
|
void MaybeSetLowQualityEncoding_Locked() EXCLUSIVE_LOCKS_REQUIRED(va_lock_);
|
||||||
|
|
||||||
|
// If a protected session is active, attaches it to the decoding context.
|
||||||
|
bool MaybeAttachProtectedSession_Locked()
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(va_lock_) WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
const CodecMode mode_;
|
||||||
|
base::SequenceCheckerImpl sequence_checker_;
|
||||||
|
|
||||||
|
// Pointer to VADisplayState's member |va_lock_|. Guaranteed to be valid for
|
||||||
|
// the lifetime of VaapiWrapper.
|
||||||
|
base::Lock* va_lock_;
|
||||||
|
|
||||||
|
// VA handles.
|
||||||
|
// All valid after successful Initialize() and until Deinitialize().
|
||||||
|
VADisplay va_display_ GUARDED_BY(va_lock_);
|
||||||
|
VAConfigID va_config_id_{VA_INVALID_ID};
|
||||||
|
// Created in CreateContext() or CreateContextAndSurfaces() and valid until
|
||||||
|
// DestroyContext() or DestroyContextAndSurfaces().
|
||||||
|
VAContextID va_context_id_{VA_INVALID_ID};
|
||||||
|
|
||||||
|
// Profile and entrypoint configured for the corresponding |va_context_id_|.
|
||||||
|
VAProfile va_profile_;
|
||||||
|
VAEntrypoint va_entrypoint_;
|
||||||
|
|
||||||
|
// Data queued up for HW codec, to be committed on next execution.
|
||||||
|
// TODO(b/166646505): let callers manage the lifetime of these buffers.
|
||||||
|
std::vector<VABufferID> pending_va_buffers_;
|
||||||
|
|
||||||
|
// VA buffer to be used for kVideoProcess. Allocated the first time around,
|
||||||
|
// and reused afterwards.
|
||||||
|
std::unique_ptr<ScopedVABuffer> va_buffer_for_vpp_;
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
// For protected decode mode.
|
||||||
|
VAConfigID va_protected_config_id_{VA_INVALID_ID};
|
||||||
|
VAProtectedSessionID va_protected_session_id_{VA_INVALID_ID};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Called to report codec errors to UMA. Errors to clients are reported via
|
||||||
|
// return values from public methods.
|
||||||
|
ReportErrorToUMACB report_error_to_uma_cb_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
|
||||||
|
#endif // MEDIA_GPU_VAAPI_VAAPI_WRAPPER_H_
|
1146
ui/base/x/x11_util.cc
Normal file
677
v8/src/objects/js-display-names.cc
Normal file
|
@ -0,0 +1,677 @@
|
||||||
|
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef V8_INTL_SUPPORT
|
||||||
|
#error Internationalization is expected to be enabled.
|
||||||
|
#endif // V8_INTL_SUPPORT
|
||||||
|
|
||||||
|
#include "src/objects/js-display-names.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "src/execution/isolate.h"
|
||||||
|
#include "src/heap/factory.h"
|
||||||
|
#include "src/objects/intl-objects.h"
|
||||||
|
#include "src/objects/js-display-names-inl.h"
|
||||||
|
#include "src/objects/managed-inl.h"
|
||||||
|
#include "src/objects/objects-inl.h"
|
||||||
|
#include "src/objects/option-utils.h"
|
||||||
|
#include "unicode/dtfmtsym.h"
|
||||||
|
#include "unicode/dtptngen.h"
|
||||||
|
#include "unicode/localebuilder.h"
|
||||||
|
#include "unicode/locdspnm.h"
|
||||||
|
#include "unicode/measfmt.h"
|
||||||
|
#include "unicode/timezone.h"
|
||||||
|
#include "unicode/tznames.h"
|
||||||
|
#include "unicode/uloc.h"
|
||||||
|
#include "unicode/unistr.h"
|
||||||
|
#include "unicode/uscript.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Type: identifying the types of the display names.
|
||||||
|
//
|
||||||
|
// ecma402/#sec-properties-of-intl-displaynames-instances
|
||||||
|
enum class Type {
|
||||||
|
kUndefined,
|
||||||
|
kLanguage,
|
||||||
|
kRegion,
|
||||||
|
kScript,
|
||||||
|
kCurrency,
|
||||||
|
kCalendar,
|
||||||
|
kDateTimeField
|
||||||
|
};
|
||||||
|
|
||||||
|
bool IsUnicodeScriptSubtag(const std::string& value) {
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
icu::LocaleBuilder builder;
|
||||||
|
builder.setScript(value).build(status);
|
||||||
|
return U_SUCCESS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsUnicodeRegionSubtag(const std::string& value) {
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
icu::LocaleBuilder builder;
|
||||||
|
builder.setRegion(value).build(status);
|
||||||
|
return U_SUCCESS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
UDisplayContext ToUDisplayContext(JSDisplayNames::Style style) {
|
||||||
|
switch (style) {
|
||||||
|
case JSDisplayNames::Style::kLong:
|
||||||
|
return UDISPCTX_LENGTH_FULL;
|
||||||
|
case JSDisplayNames::Style::kShort:
|
||||||
|
case JSDisplayNames::Style::kNarrow:
|
||||||
|
return UDISPCTX_LENGTH_SHORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
// Abstract class for all different types.
|
||||||
|
class DisplayNamesInternal {
|
||||||
|
public:
|
||||||
|
DisplayNamesInternal() = default;
|
||||||
|
virtual ~DisplayNamesInternal() = default;
|
||||||
|
virtual const char* type() const = 0;
|
||||||
|
virtual icu::Locale locale() const = 0;
|
||||||
|
virtual Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class LocaleDisplayNamesCommon : public DisplayNamesInternal {
|
||||||
|
public:
|
||||||
|
LocaleDisplayNamesCommon(const icu::Locale& locale,
|
||||||
|
JSDisplayNames::Style style, bool fallback,
|
||||||
|
bool dialect)
|
||||||
|
: style_(style) {
|
||||||
|
UDisplayContext sub =
|
||||||
|
fallback ? UDISPCTX_SUBSTITUTE : UDISPCTX_NO_SUBSTITUTE;
|
||||||
|
UDisplayContext dialect_context =
|
||||||
|
dialect ? UDISPCTX_DIALECT_NAMES : UDISPCTX_STANDARD_NAMES;
|
||||||
|
UDisplayContext display_context[] = {ToUDisplayContext(style_),
|
||||||
|
dialect_context,
|
||||||
|
UDISPCTX_CAPITALIZATION_NONE, sub};
|
||||||
|
ldn_.reset(
|
||||||
|
icu::LocaleDisplayNames::createInstance(locale, display_context, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
~LocaleDisplayNamesCommon() override = default;
|
||||||
|
|
||||||
|
icu::Locale locale() const override { return ldn_->getLocale(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
icu::LocaleDisplayNames* locale_display_names() const { return ldn_.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<icu::LocaleDisplayNames> ldn_;
|
||||||
|
JSDisplayNames::Style style_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LanguageNames : public LocaleDisplayNamesCommon {
|
||||||
|
public:
|
||||||
|
LanguageNames(const icu::Locale& locale, JSDisplayNames::Style style,
|
||||||
|
bool fallback, bool dialect)
|
||||||
|
: LocaleDisplayNamesCommon(locale, style, fallback, dialect) {}
|
||||||
|
|
||||||
|
~LanguageNames() override = default;
|
||||||
|
|
||||||
|
const char* type() const override { return "language"; }
|
||||||
|
|
||||||
|
Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const override {
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
// 1.a If code does not match the unicode_language_id production, throw a
|
||||||
|
// RangeError exception.
|
||||||
|
|
||||||
|
// 1.b If IsStructurallyValidLanguageTag(code) is false, throw a RangeError
|
||||||
|
// exception.
|
||||||
|
icu::Locale l =
|
||||||
|
icu::Locale::createCanonical(icu::Locale::forLanguageTag(code, status).getBaseName());
|
||||||
|
std::string checked = l.toLanguageTag<std::string>(status);
|
||||||
|
|
||||||
|
if (U_FAILURE(status)) {
|
||||||
|
THROW_NEW_ERROR_RETURN_VALUE(
|
||||||
|
isolate, NewRangeError(MessageTemplate::kInvalidArgument),
|
||||||
|
Nothing<icu::UnicodeString>());
|
||||||
|
}
|
||||||
|
|
||||||
|
icu::UnicodeString result;
|
||||||
|
locale_display_names()->localeDisplayName(checked.c_str(), result);
|
||||||
|
|
||||||
|
return Just(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegionNames : public LocaleDisplayNamesCommon {
|
||||||
|
public:
|
||||||
|
RegionNames(const icu::Locale& locale, JSDisplayNames::Style style,
|
||||||
|
bool fallback, bool dialect)
|
||||||
|
: LocaleDisplayNamesCommon(locale, style, fallback, dialect) {}
|
||||||
|
|
||||||
|
~RegionNames() override = default;
|
||||||
|
|
||||||
|
const char* type() const override { return "region"; }
|
||||||
|
|
||||||
|
Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const override {
|
||||||
|
std::string code_str(code);
|
||||||
|
if (!IsUnicodeRegionSubtag(code_str)) {
|
||||||
|
THROW_NEW_ERROR_RETURN_VALUE(
|
||||||
|
isolate, NewRangeError(MessageTemplate::kInvalidArgument),
|
||||||
|
Nothing<icu::UnicodeString>());
|
||||||
|
}
|
||||||
|
|
||||||
|
icu::UnicodeString result;
|
||||||
|
locale_display_names()->regionDisplayName(code_str.c_str(), result);
|
||||||
|
return Just(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScriptNames : public LocaleDisplayNamesCommon {
|
||||||
|
public:
|
||||||
|
ScriptNames(const icu::Locale& locale, JSDisplayNames::Style style,
|
||||||
|
bool fallback, bool dialect)
|
||||||
|
: LocaleDisplayNamesCommon(locale, style, fallback, dialect) {}
|
||||||
|
|
||||||
|
~ScriptNames() override = default;
|
||||||
|
|
||||||
|
const char* type() const override { return "script"; }
|
||||||
|
|
||||||
|
Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const override {
|
||||||
|
std::string code_str(code);
|
||||||
|
if (!IsUnicodeScriptSubtag(code_str)) {
|
||||||
|
THROW_NEW_ERROR_RETURN_VALUE(
|
||||||
|
isolate, NewRangeError(MessageTemplate::kInvalidArgument),
|
||||||
|
Nothing<icu::UnicodeString>());
|
||||||
|
}
|
||||||
|
|
||||||
|
icu::UnicodeString result;
|
||||||
|
locale_display_names()->scriptDisplayName(code_str.c_str(), result);
|
||||||
|
return Just(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyValueDisplayNames : public LocaleDisplayNamesCommon {
|
||||||
|
public:
|
||||||
|
KeyValueDisplayNames(const icu::Locale& locale, JSDisplayNames::Style style,
|
||||||
|
bool fallback, bool dialect, const char* key,
|
||||||
|
bool prevent_fallback)
|
||||||
|
: LocaleDisplayNamesCommon(locale, style, fallback, dialect),
|
||||||
|
key_(key),
|
||||||
|
prevent_fallback_(prevent_fallback) {}
|
||||||
|
|
||||||
|
~KeyValueDisplayNames() override = default;
|
||||||
|
|
||||||
|
const char* type() const override { return key_.c_str(); }
|
||||||
|
|
||||||
|
Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const override {
|
||||||
|
std::string code_str(code);
|
||||||
|
icu::UnicodeString result;
|
||||||
|
locale_display_names()->keyValueDisplayName(key_.c_str(), code_str.c_str(),
|
||||||
|
result);
|
||||||
|
// Work around the issue that the keyValueDisplayNames ignore no
|
||||||
|
// substituion and always fallback.
|
||||||
|
if (prevent_fallback_ && (result.length() == 3) &&
|
||||||
|
(code_str.length() == 3) &&
|
||||||
|
(result == icu::UnicodeString(code_str.c_str(), -1, US_INV))) {
|
||||||
|
result.setToBogus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Just(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string key_;
|
||||||
|
bool prevent_fallback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CurrencyNames : public KeyValueDisplayNames {
|
||||||
|
public:
|
||||||
|
CurrencyNames(const icu::Locale& locale, JSDisplayNames::Style style,
|
||||||
|
bool fallback, bool dialect)
|
||||||
|
: KeyValueDisplayNames(locale, style, fallback, dialect, "currency",
|
||||||
|
fallback == false) {}
|
||||||
|
|
||||||
|
~CurrencyNames() override = default;
|
||||||
|
|
||||||
|
Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const override {
|
||||||
|
std::string code_str(code);
|
||||||
|
if (!Intl::IsWellFormedCurrency(code_str)) {
|
||||||
|
THROW_NEW_ERROR_RETURN_VALUE(
|
||||||
|
isolate, NewRangeError(MessageTemplate::kInvalidArgument),
|
||||||
|
Nothing<icu::UnicodeString>());
|
||||||
|
}
|
||||||
|
return KeyValueDisplayNames::of(isolate, code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CalendarNames : public KeyValueDisplayNames {
|
||||||
|
public:
|
||||||
|
CalendarNames(const icu::Locale& locale, JSDisplayNames::Style style,
|
||||||
|
bool fallback, bool dialect)
|
||||||
|
: KeyValueDisplayNames(locale, style, fallback, dialect, "calendar",
|
||||||
|
false) {}
|
||||||
|
|
||||||
|
~CalendarNames() override = default;
|
||||||
|
|
||||||
|
Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const override {
|
||||||
|
std::string code_str(code);
|
||||||
|
if (!Intl::IsWellFormedCalendar(code_str)) {
|
||||||
|
THROW_NEW_ERROR_RETURN_VALUE(
|
||||||
|
isolate, NewRangeError(MessageTemplate::kInvalidArgument),
|
||||||
|
Nothing<icu::UnicodeString>());
|
||||||
|
}
|
||||||
|
return KeyValueDisplayNames::of(isolate, strcmp(code, "gregory") == 0
|
||||||
|
? "gregorian"
|
||||||
|
: strcmp(code, "ethioaa") == 0
|
||||||
|
? "ethiopic-amete-alem"
|
||||||
|
: code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UDateTimePGDisplayWidth StyleToUDateTimePGDisplayWidth(
|
||||||
|
JSDisplayNames::Style style) {
|
||||||
|
switch (style) {
|
||||||
|
case JSDisplayNames::Style::kLong:
|
||||||
|
return UDATPG_WIDE;
|
||||||
|
case JSDisplayNames::Style::kShort:
|
||||||
|
return UDATPG_ABBREVIATED;
|
||||||
|
case JSDisplayNames::Style::kNarrow:
|
||||||
|
return UDATPG_NARROW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UDateTimePatternField StringToUDateTimePatternField(const char* code) {
|
||||||
|
switch (code[0]) {
|
||||||
|
case 'd':
|
||||||
|
if (strcmp(code, "day") == 0) return UDATPG_DAY_FIELD;
|
||||||
|
if (strcmp(code, "dayPeriod") == 0) return UDATPG_DAYPERIOD_FIELD;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
if (strcmp(code, "era") == 0) return UDATPG_ERA_FIELD;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
if (strcmp(code, "hour") == 0) return UDATPG_HOUR_FIELD;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (strcmp(code, "minute") == 0) return UDATPG_MINUTE_FIELD;
|
||||||
|
if (strcmp(code, "month") == 0) return UDATPG_MONTH_FIELD;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
if (strcmp(code, "quarter") == 0) return UDATPG_QUARTER_FIELD;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (strcmp(code, "second") == 0) return UDATPG_SECOND_FIELD;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
if (strcmp(code, "timeZoneName") == 0) return UDATPG_ZONE_FIELD;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
if (strcmp(code, "weekOfYear") == 0) return UDATPG_WEEK_OF_YEAR_FIELD;
|
||||||
|
if (strcmp(code, "weekday") == 0) return UDATPG_WEEKDAY_FIELD;
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
if (strcmp(code, "year") == 0) return UDATPG_YEAR_FIELD;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return UDATPG_FIELD_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DateTimeFieldNames : public DisplayNamesInternal {
|
||||||
|
public:
|
||||||
|
DateTimeFieldNames(const icu::Locale& locale, JSDisplayNames::Style style,
|
||||||
|
bool fallback)
|
||||||
|
: locale_(locale), width_(StyleToUDateTimePGDisplayWidth(style)) {
|
||||||
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
generator_.reset(
|
||||||
|
icu::DateTimePatternGenerator::createInstance(locale_, status));
|
||||||
|
DCHECK(U_SUCCESS(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
~DateTimeFieldNames() override = default;
|
||||||
|
|
||||||
|
const char* type() const override { return "dateTimeField"; }
|
||||||
|
|
||||||
|
icu::Locale locale() const override { return locale_; }
|
||||||
|
|
||||||
|
Maybe<icu::UnicodeString> of(Isolate* isolate,
|
||||||
|
const char* code) const override {
|
||||||
|
UDateTimePatternField field = StringToUDateTimePatternField(code);
|
||||||
|
if (field == UDATPG_FIELD_COUNT) {
|
||||||
|
THROW_NEW_ERROR_RETURN_VALUE(
|
||||||
|
isolate, NewRangeError(MessageTemplate::kInvalidArgument),
|
||||||
|
Nothing<icu::UnicodeString>());
|
||||||
|
}
|
||||||
|
return Just(generator_->getFieldDisplayName(field, width_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
icu::Locale locale_;
|
||||||
|
UDateTimePGDisplayWidth width_;
|
||||||
|
std::unique_ptr<icu::DateTimePatternGenerator> generator_;
|
||||||
|
};
|
||||||
|
|
||||||
|
DisplayNamesInternal* CreateInternal(const icu::Locale& locale,
|
||||||
|
JSDisplayNames::Style style, Type type,
|
||||||
|
bool fallback, bool dialect) {
|
||||||
|
switch (type) {
|
||||||
|
case Type::kLanguage:
|
||||||
|
return new LanguageNames(locale, style, fallback, dialect);
|
||||||
|
case Type::kRegion:
|
||||||
|
return new RegionNames(locale, style, fallback, false);
|
||||||
|
case Type::kScript:
|
||||||
|
return new ScriptNames(locale, style, fallback, false);
|
||||||
|
case Type::kCurrency:
|
||||||
|
return new CurrencyNames(locale, style, fallback, false);
|
||||||
|
case Type::kCalendar:
|
||||||
|
return new CalendarNames(locale, style, fallback, false);
|
||||||
|
case Type::kDateTimeField:
|
||||||
|
return new DateTimeFieldNames(locale, style, fallback);
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
// ecma402 #sec-Intl.DisplayNames
|
||||||
|
MaybeHandle<JSDisplayNames> JSDisplayNames::New(Isolate* isolate,
|
||||||
|
Handle<Map> map,
|
||||||
|
Handle<Object> locales,
|
||||||
|
Handle<Object> input_options) {
|
||||||
|
const char* service = "Intl.DisplayNames";
|
||||||
|
Factory* factory = isolate->factory();
|
||||||
|
|
||||||
|
Handle<JSReceiver> options;
|
||||||
|
// 3. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||||
|
Maybe<std::vector<std::string>> maybe_requested_locales =
|
||||||
|
Intl::CanonicalizeLocaleList(isolate, locales);
|
||||||
|
MAYBE_RETURN(maybe_requested_locales, Handle<JSDisplayNames>());
|
||||||
|
std::vector<std::string> requested_locales =
|
||||||
|
maybe_requested_locales.FromJust();
|
||||||
|
|
||||||
|
// 4. Let options be ? GetOptionsObject(options).
|
||||||
|
ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
|
||||||
|
GetOptionsObject(isolate, input_options, service),
|
||||||
|
JSDisplayNames);
|
||||||
|
|
||||||
|
// Note: No need to create a record. It's not observable.
|
||||||
|
// 5. Let opt be a new Record.
|
||||||
|
|
||||||
|
// 6. Let localeData be %DisplayNames%.[[LocaleData]].
|
||||||
|
|
||||||
|
// 7. Let matcher be ? GetOption(options, "localeMatcher", "string", «
|
||||||
|
// "lookup", "best fit" », "best fit").
|
||||||
|
Maybe<Intl::MatcherOption> maybe_locale_matcher =
|
||||||
|
Intl::GetLocaleMatcher(isolate, options, service);
|
||||||
|
MAYBE_RETURN(maybe_locale_matcher, MaybeHandle<JSDisplayNames>());
|
||||||
|
|
||||||
|
// 8. Set opt.[[localeMatcher]] to matcher.
|
||||||
|
Intl::MatcherOption matcher = maybe_locale_matcher.FromJust();
|
||||||
|
|
||||||
|
// ecma402/#sec-Intl.DisplayNames-internal-slots
|
||||||
|
// The value of the [[RelevantExtensionKeys]] internal slot is
|
||||||
|
// « ».
|
||||||
|
std::set<std::string> relevant_extension_keys = {};
|
||||||
|
// 9. Let r be ResolveLocale(%DisplayNames%.[[AvailableLocales]],
|
||||||
|
// requestedLocales, opt, %DisplayNames%.[[RelevantExtensionKeys]]).
|
||||||
|
Maybe<Intl::ResolvedLocale> maybe_resolve_locale =
|
||||||
|
Intl::ResolveLocale(isolate, JSDisplayNames::GetAvailableLocales(),
|
||||||
|
requested_locales, matcher, relevant_extension_keys);
|
||||||
|
if (maybe_resolve_locale.IsNothing()) {
|
||||||
|
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError),
|
||||||
|
JSDisplayNames);
|
||||||
|
}
|
||||||
|
Intl::ResolvedLocale r = maybe_resolve_locale.FromJust();
|
||||||
|
|
||||||
|
icu::Locale icu_locale = r.icu_locale;
|
||||||
|
|
||||||
|
// 10. Let s be ? GetOption(options, "style", "string",
|
||||||
|
// «"long", "short", "narrow"», "long").
|
||||||
|
Maybe<Style> maybe_style = GetStringOption<Style>(
|
||||||
|
isolate, options, "style", service, {"long", "short", "narrow"},
|
||||||
|
{Style::kLong, Style::kShort, Style::kNarrow}, Style::kLong);
|
||||||
|
MAYBE_RETURN(maybe_style, MaybeHandle<JSDisplayNames>());
|
||||||
|
Style style_enum = maybe_style.FromJust();
|
||||||
|
|
||||||
|
// 11. Set displayNames.[[Style]] to style.
|
||||||
|
|
||||||
|
// 12. Let type be ? GetOption(options, "type", "string", « "language",
|
||||||
|
// "region", "script", "currency" , "calendar", "dateTimeField", "unit"»,
|
||||||
|
// undefined).
|
||||||
|
Maybe<Type> maybe_type =
|
||||||
|
FLAG_harmony_intl_displaynames_v2
|
||||||
|
? GetStringOption<Type>(
|
||||||
|
isolate, options, "type", service,
|
||||||
|
{"language", "region", "script", "currency", "calendar",
|
||||||
|
"dateTimeField"},
|
||||||
|
{Type::kLanguage, Type::kRegion, Type::kScript, Type::kCurrency,
|
||||||
|
Type::kCalendar, Type::kDateTimeField},
|
||||||
|
Type::kUndefined)
|
||||||
|
: GetStringOption<Type>(isolate, options, "type", service,
|
||||||
|
{"language", "region", "script", "currency"},
|
||||||
|
{
|
||||||
|
Type::kLanguage,
|
||||||
|
Type::kRegion,
|
||||||
|
Type::kScript,
|
||||||
|
Type::kCurrency,
|
||||||
|
},
|
||||||
|
Type::kUndefined);
|
||||||
|
MAYBE_RETURN(maybe_type, MaybeHandle<JSDisplayNames>());
|
||||||
|
Type type_enum = maybe_type.FromJust();
|
||||||
|
|
||||||
|
// 13. If type is undefined, throw a TypeError exception.
|
||||||
|
if (type_enum == Type::kUndefined) {
|
||||||
|
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidArgument),
|
||||||
|
JSDisplayNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 14. Set displayNames.[[Type]] to type.
|
||||||
|
|
||||||
|
// 15. Let fallback be ? GetOption(options, "fallback", "string",
|
||||||
|
// « "code", "none" », "code").
|
||||||
|
Maybe<Fallback> maybe_fallback = GetStringOption<Fallback>(
|
||||||
|
isolate, options, "fallback", service, {"code", "none"},
|
||||||
|
{Fallback::kCode, Fallback::kNone}, Fallback::kCode);
|
||||||
|
MAYBE_RETURN(maybe_fallback, MaybeHandle<JSDisplayNames>());
|
||||||
|
Fallback fallback_enum = maybe_fallback.FromJust();
|
||||||
|
|
||||||
|
// 16. Set displayNames.[[Fallback]] to fallback.
|
||||||
|
|
||||||
|
LanguageDisplay language_display_enum = LanguageDisplay::kDialect;
|
||||||
|
if (FLAG_harmony_intl_displaynames_v2) {
|
||||||
|
// 24. Let languageDisplay be ? GetOption(options, "languageDisplay",
|
||||||
|
// "string", « "dialect", "standard" », "dialect").
|
||||||
|
Maybe<LanguageDisplay> maybe_language_display =
|
||||||
|
GetStringOption<LanguageDisplay>(
|
||||||
|
isolate, options, "languageDisplay", service,
|
||||||
|
{"dialect", "standard"},
|
||||||
|
{LanguageDisplay::kDialect, LanguageDisplay::kStandard},
|
||||||
|
LanguageDisplay::kDialect);
|
||||||
|
MAYBE_RETURN(maybe_language_display, MaybeHandle<JSDisplayNames>());
|
||||||
|
// 25. If type is "language", then
|
||||||
|
if (type_enum == Type::kLanguage) {
|
||||||
|
// a. Set displayNames.[[LanguageDisplay]] to languageDisplay.
|
||||||
|
language_display_enum = maybe_language_display.FromJust();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set displayNames.[[Fallback]] to fallback.
|
||||||
|
|
||||||
|
// 17. Set displayNames.[[Locale]] to the value of r.[[Locale]].
|
||||||
|
|
||||||
|
// Let dataLocale be r.[[dataLocale]].
|
||||||
|
|
||||||
|
// Let dataLocaleData be localeData.[[<dataLocale>]].
|
||||||
|
|
||||||
|
// Let types be dataLocaleData.[[types]].
|
||||||
|
|
||||||
|
// Assert: types is a Record (see 1.3.3).
|
||||||
|
|
||||||
|
// Let typeFields be types.[[<type>]].
|
||||||
|
|
||||||
|
// Assert: typeFields is a Record (see 1.3.3).
|
||||||
|
|
||||||
|
// Let styleFields be typeFields.[[<style>]].
|
||||||
|
|
||||||
|
// Assert: styleFields is a Record (see 1.3.3).
|
||||||
|
|
||||||
|
// Set displayNames.[[Fields]] to styleFields.
|
||||||
|
|
||||||
|
DisplayNamesInternal* internal = CreateInternal(
|
||||||
|
icu_locale, style_enum, type_enum, fallback_enum == Fallback::kCode,
|
||||||
|
language_display_enum == LanguageDisplay::kDialect);
|
||||||
|
if (internal == nullptr) {
|
||||||
|
THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIcuError),
|
||||||
|
JSDisplayNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<Managed<DisplayNamesInternal>> managed_internal =
|
||||||
|
Managed<DisplayNamesInternal>::FromRawPtr(isolate, 0, internal);
|
||||||
|
|
||||||
|
Handle<JSDisplayNames> display_names =
|
||||||
|
Handle<JSDisplayNames>::cast(factory->NewFastOrSlowJSObjectFromMap(map));
|
||||||
|
display_names->set_flags(0);
|
||||||
|
display_names->set_style(style_enum);
|
||||||
|
display_names->set_fallback(fallback_enum);
|
||||||
|
display_names->set_language_display(language_display_enum);
|
||||||
|
|
||||||
|
DisallowGarbageCollection no_gc;
|
||||||
|
display_names->set_internal(*managed_internal);
|
||||||
|
|
||||||
|
// Return displayNames.
|
||||||
|
return display_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ecma402 #sec-Intl.DisplayNames.prototype.resolvedOptions
|
||||||
|
Handle<JSObject> JSDisplayNames::ResolvedOptions(
|
||||||
|
Isolate* isolate, Handle<JSDisplayNames> display_names) {
|
||||||
|
Factory* factory = isolate->factory();
|
||||||
|
// 4. Let options be ! ObjectCreate(%ObjectPrototype%).
|
||||||
|
Handle<JSObject> options = factory->NewJSObject(isolate->object_function());
|
||||||
|
|
||||||
|
DisplayNamesInternal* internal = display_names->internal().raw();
|
||||||
|
|
||||||
|
Maybe<std::string> maybe_locale = Intl::ToLanguageTag(internal->locale());
|
||||||
|
DCHECK(maybe_locale.IsJust());
|
||||||
|
Handle<String> locale = isolate->factory()->NewStringFromAsciiChecked(
|
||||||
|
maybe_locale.FromJust().c_str());
|
||||||
|
Handle<String> style = display_names->StyleAsString();
|
||||||
|
Handle<String> type = factory->NewStringFromAsciiChecked(internal->type());
|
||||||
|
Handle<String> fallback = display_names->FallbackAsString();
|
||||||
|
Handle<String> language_display = display_names->LanguageDisplayAsString();
|
||||||
|
|
||||||
|
Maybe<bool> maybe_create_locale = JSReceiver::CreateDataProperty(
|
||||||
|
isolate, options, factory->locale_string(), locale, Just(kDontThrow));
|
||||||
|
DCHECK(maybe_create_locale.FromJust());
|
||||||
|
USE(maybe_create_locale);
|
||||||
|
|
||||||
|
Maybe<bool> maybe_create_style = JSReceiver::CreateDataProperty(
|
||||||
|
isolate, options, factory->style_string(), style, Just(kDontThrow));
|
||||||
|
DCHECK(maybe_create_style.FromJust());
|
||||||
|
USE(maybe_create_style);
|
||||||
|
|
||||||
|
Maybe<bool> maybe_create_type = JSReceiver::CreateDataProperty(
|
||||||
|
isolate, options, factory->type_string(), type, Just(kDontThrow));
|
||||||
|
DCHECK(maybe_create_type.FromJust());
|
||||||
|
USE(maybe_create_type);
|
||||||
|
|
||||||
|
Maybe<bool> maybe_create_fallback = JSReceiver::CreateDataProperty(
|
||||||
|
isolate, options, factory->fallback_string(), fallback, Just(kDontThrow));
|
||||||
|
DCHECK(maybe_create_fallback.FromJust());
|
||||||
|
USE(maybe_create_fallback);
|
||||||
|
|
||||||
|
if (FLAG_harmony_intl_displaynames_v2) {
|
||||||
|
if (std::strcmp("language", internal->type()) == 0) {
|
||||||
|
Maybe<bool> maybe_create_language_display =
|
||||||
|
JSReceiver::CreateDataProperty(isolate, options,
|
||||||
|
factory->languageDisplay_string(),
|
||||||
|
language_display, Just(kDontThrow));
|
||||||
|
DCHECK(maybe_create_language_display.FromJust());
|
||||||
|
USE(maybe_create_language_display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ecma402 #sec-Intl.DisplayNames.prototype.of
|
||||||
|
MaybeHandle<Object> JSDisplayNames::Of(Isolate* isolate,
|
||||||
|
Handle<JSDisplayNames> display_names,
|
||||||
|
Handle<Object> code_obj) {
|
||||||
|
Handle<String> code;
|
||||||
|
ASSIGN_RETURN_ON_EXCEPTION(isolate, code, Object::ToString(isolate, code_obj),
|
||||||
|
Object);
|
||||||
|
DisplayNamesInternal* internal = display_names->internal().raw();
|
||||||
|
Maybe<icu::UnicodeString> maybe_result =
|
||||||
|
internal->of(isolate, code->ToCString().get());
|
||||||
|
MAYBE_RETURN(maybe_result, Handle<Object>());
|
||||||
|
icu::UnicodeString result = maybe_result.FromJust();
|
||||||
|
if (result.isBogus()) {
|
||||||
|
return isolate->factory()->undefined_value();
|
||||||
|
}
|
||||||
|
return Intl::ToString(isolate, result).ToHandleChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct CheckCalendar {
|
||||||
|
static const char* key() { return "calendar"; }
|
||||||
|
static const char* path() { return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
const std::set<std::string>& JSDisplayNames::GetAvailableLocales() {
|
||||||
|
static base::LazyInstance<Intl::AvailableLocales<CheckCalendar>>::type
|
||||||
|
available_locales = LAZY_INSTANCE_INITIALIZER;
|
||||||
|
return available_locales.Pointer()->Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<String> JSDisplayNames::StyleAsString() const {
|
||||||
|
switch (style()) {
|
||||||
|
case Style::kLong:
|
||||||
|
return GetReadOnlyRoots().long_string_handle();
|
||||||
|
case Style::kShort:
|
||||||
|
return GetReadOnlyRoots().short_string_handle();
|
||||||
|
case Style::kNarrow:
|
||||||
|
return GetReadOnlyRoots().narrow_string_handle();
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<String> JSDisplayNames::FallbackAsString() const {
|
||||||
|
switch (fallback()) {
|
||||||
|
case Fallback::kCode:
|
||||||
|
return GetReadOnlyRoots().code_string_handle();
|
||||||
|
case Fallback::kNone:
|
||||||
|
return GetReadOnlyRoots().none_string_handle();
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<String> JSDisplayNames::LanguageDisplayAsString() const {
|
||||||
|
switch (language_display()) {
|
||||||
|
case LanguageDisplay::kDialect:
|
||||||
|
return GetReadOnlyRoots().dialect_string_handle();
|
||||||
|
case LanguageDisplay::kStandard:
|
||||||
|
return GetReadOnlyRoots().standard_string_handle();
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|