mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70a66589ae | ||
|
|
6d5b65ec35 | ||
|
|
ec2adf0b2e | ||
|
|
2d9eaffb98 | ||
|
|
3d3bd64ab2 | ||
|
|
8b9170b664 | ||
|
|
6b2c470f46 | ||
|
|
f53fad8abb | ||
|
|
7b2c526a43 | ||
|
|
1da86c0fbf | ||
|
|
166bcd3208 | ||
|
|
133cd29201 | ||
|
|
3511eb1a8e | ||
|
|
426cd1d68c | ||
|
|
2c152014c4 | ||
|
|
d1a6d98a93 | ||
|
|
ea680012de | ||
|
|
d635f34565 | ||
|
|
18bf1d2f59 | ||
|
|
4a0d4975f3 | ||
|
|
56ac51cfa2 | ||
|
|
d297808531 | ||
|
|
077c4addd5 | ||
|
|
c3c5734fa8 | ||
|
|
62c97ffecf | ||
|
|
24b841cbcd | ||
|
|
b1377d42d9 | ||
|
|
ca92ebff25 |
@@ -75,10 +75,6 @@ executors:
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# Electron Runners
|
||||
apple-silicon:
|
||||
resource_class: electronjs/macos-arm64
|
||||
machine: true
|
||||
|
||||
linux-arm:
|
||||
resource_class: electronjs/aks-linux-arm-test
|
||||
docker:
|
||||
@@ -252,6 +248,10 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
name: Get depot tools
|
||||
command: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
# remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems
|
||||
sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
@@ -2326,8 +2326,11 @@ jobs:
|
||||
- electron-tests:
|
||||
artifact-key: darwin-x64
|
||||
|
||||
darwin-testing-arm64-tests:
|
||||
executor: apple-silicon
|
||||
darwin-testing-arm64-tests:
|
||||
executor:
|
||||
name: macos
|
||||
size: macos.m1.medium.gen1
|
||||
version: 14.0.0
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
@@ -2351,7 +2354,10 @@ jobs:
|
||||
artifact-key: mas-x64
|
||||
|
||||
mas-testing-arm64-tests:
|
||||
executor: apple-silicon
|
||||
executor:
|
||||
name: macos
|
||||
size: macos.m1.medium.gen1
|
||||
version: 14.0.0
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
|
||||
@@ -94,6 +94,11 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
|
||||
@@ -92,6 +92,11 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
|
||||
@@ -15,4 +15,15 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
|
||||
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
|
||||
]
|
||||
|
||||
if (electron_vendor_version != "") {
|
||||
result = string_split(electron_vendor_version, ":")
|
||||
flags += [
|
||||
"HAS_VENDOR_VERSION=true",
|
||||
"VENDOR_VERSION_NAME=\"${result[0]}\"",
|
||||
"VENDOR_VERSION_VALUE=\"${result[1]}\"",
|
||||
]
|
||||
} else {
|
||||
flags += [ "HAS_VENDOR_VERSION=false" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,10 @@ declare_args() {
|
||||
# Packagers and vendor builders should set this in gn args to avoid running
|
||||
# the script that reads git tag.
|
||||
override_electron_version = ""
|
||||
|
||||
# Define an extra item that will show in process.versions, the value must
|
||||
# be in the format of "key:value".
|
||||
# Packagers and vendor builders can set this in gn args to attach extra info
|
||||
# about the build in the binary.
|
||||
electron_vendor_version = ""
|
||||
}
|
||||
|
||||
@@ -51,6 +51,13 @@ Check the _Size requirements_ section in [this article][icons].
|
||||
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-icons
|
||||
|
||||
:::note
|
||||
|
||||
EXIF metadata is currently not supported and will not be taken into account during
|
||||
image encoding and decoding.
|
||||
|
||||
:::
|
||||
|
||||
## High Resolution Image
|
||||
|
||||
On platforms that have high-DPI support such as Apple Retina displays, you can
|
||||
|
||||
@@ -3,14 +3,14 @@ import { wrapFsWithAsar } from './asar-fs-wrapper';
|
||||
wrapFsWithAsar(require('fs'));
|
||||
|
||||
// Hook child_process.fork.
|
||||
const cp = require('child_process');
|
||||
import cp = require('child_process'); // eslint-disable-line import/first
|
||||
const originalFork = cp.fork;
|
||||
cp.fork = (modulePath: string, args: any, options: any) => {
|
||||
cp.fork = (modulePath, args?, options?: cp.ForkOptions) => {
|
||||
// Parse optional args.
|
||||
if (args == null) {
|
||||
args = [];
|
||||
} else if (typeof args === 'object' && !Array.isArray(args)) {
|
||||
options = args;
|
||||
options = args as cp.ForkOptions;
|
||||
args = [];
|
||||
}
|
||||
// Fallback to original fork to report arg type errors.
|
||||
@@ -22,7 +22,7 @@ cp.fork = (modulePath: string, args: any, options: any) => {
|
||||
// the electron binary run like upstream Node.js.
|
||||
options = options ?? {};
|
||||
options.env = Object.create(options.env || process.env);
|
||||
options.env.ELECTRON_RUN_AS_NODE = 1;
|
||||
options.env!.ELECTRON_RUN_AS_NODE = '1';
|
||||
// On mac the child script runs in helper executable.
|
||||
if (!options.execPath && process.platform === 'darwin') {
|
||||
options.execPath = process.helperExecPath;
|
||||
@@ -31,7 +31,7 @@ cp.fork = (modulePath: string, args: any, options: any) => {
|
||||
};
|
||||
|
||||
// Prevent Node from adding paths outside this app to search paths.
|
||||
const path = require('path');
|
||||
import path = require('path'); // eslint-disable-line import/first
|
||||
const Module = require('module');
|
||||
const resourcesPathWithTrailingSlash = process.resourcesPath + path.sep;
|
||||
const originalNodeModulePaths = Module._nodeModulePaths;
|
||||
|
||||
2
patches/DirectXShaderCompiler/.patches
Normal file
2
patches/DirectXShaderCompiler/.patches
Normal file
@@ -0,0 +1,2 @@
|
||||
fix_hlmatrixlowerpass_leaving_call_to_dangling_functionval.patch
|
||||
cherry-pick-a65e511a14b4.patch
|
||||
66
patches/DirectXShaderCompiler/cherry-pick-a65e511a14b4.patch
Normal file
66
patches/DirectXShaderCompiler/cherry-pick-a65e511a14b4.patch
Normal file
@@ -0,0 +1,66 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Maiorano <amaiorano@google.com>
|
||||
Date: Wed, 3 Apr 2024 15:58:51 -0400
|
||||
Subject: Fix ASAN use-after-free on unreferenced self-assignment of struct
|
||||
instance (#6466)
|
||||
|
||||
When deleting an unused memcpy, ScalarReplAggregatesHLSL was attempting
|
||||
to delete both the target and the source of the memcpy without first
|
||||
checking if they were both same, resulting in a double-delete.
|
||||
|
||||
Bug: chromium:331123811
|
||||
Change-Id: Idaef95a06b10a7fb6f0ca2e662972a44ec662fbc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5419225
|
||||
Reviewed-by: David Neto <dneto@google.com>
|
||||
Reviewed-by: dan sinclair <dsinclair@chromium.org>
|
||||
Reviewed-by: Ben Clayton <bclayton@chromium.org>
|
||||
|
||||
diff --git a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
index b3589884aa3b690e1aad5ca7a19218a222591d39..8e2eff7f69ec378393c7a9afc4040cd9e921c42d 100644
|
||||
--- a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
+++ b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
@@ -989,9 +989,11 @@ void DeleteMemcpy(MemCpyInst *MI) {
|
||||
if (op0->user_empty())
|
||||
op0->eraseFromParent();
|
||||
}
|
||||
- if (Instruction *op1 = dyn_cast<Instruction>(Op1)) {
|
||||
- if (op1->user_empty())
|
||||
- op1->eraseFromParent();
|
||||
+ if (Op0 != Op1) {
|
||||
+ if (Instruction *op1 = dyn_cast<Instruction>(Op1)) {
|
||||
+ if (op1->user_empty())
|
||||
+ op1->eraseFromParent();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/tools/clang/test/DXC/unreferenced_struct_selft_assignment_crash.hlsl b/tools/clang/test/DXC/unreferenced_struct_selft_assignment_crash.hlsl
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..81adf71867c9868992372e12dc1ba81aebb48344
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/DXC/unreferenced_struct_selft_assignment_crash.hlsl
|
||||
@@ -0,0 +1,24 @@
|
||||
+// RUN: %dxc -T cs_6_0 %s | FileCheck %s
|
||||
+
|
||||
+// Validate that self-assignment of a static struct instance that is not
|
||||
+// referenced does not crash the compiler. This was resulting in an ASAN
|
||||
+// use-after-free in ScalarReplAggregatesHLSL because DeleteMemcpy would
|
||||
+// attempt to delete both source and target, even if both were the same.
|
||||
+// CHECK: define void @main() {
|
||||
+// CHECK-NEXT: ret void
|
||||
+// CHECK-NEXT: }
|
||||
+
|
||||
+struct MyStruct {
|
||||
+ int m0;
|
||||
+};
|
||||
+
|
||||
+static MyStruct s;
|
||||
+
|
||||
+void foo() {
|
||||
+ s = s;
|
||||
+}
|
||||
+
|
||||
+[numthreads(1, 1, 1)]
|
||||
+void main() {
|
||||
+ foo();
|
||||
+}
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Maiorano <amaiorano@google.com>
|
||||
Date: Wed, 20 Mar 2024 17:15:40 -0400
|
||||
Subject: Fix HLMatrixLowerPass leaving call to dangling FunctionVal
|
||||
|
||||
When lowering an hl.cast, when the operand was an undef matrix, the pass would insert a call to a mat2vec stub, but since the undef value is not
|
||||
an alloca, it never gets handled, and the call to the temporary stub
|
||||
remains. Since the stub FunctionVal gets deleted, when the instruction
|
||||
is accessed in a future pass, it reads a dangling pointer.
|
||||
|
||||
The fix is to handle undef similarly to how constant 0 is handled, and
|
||||
to return an undef vector from lowerHLCast.
|
||||
|
||||
Bug: chromium:328958020
|
||||
Change-Id: Id31e3aa326d9cb9f03ea97139f14dc5292cd6f7b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5383595
|
||||
Reviewed-by: Ben Clayton <bclayton@chromium.org>
|
||||
Reviewed-by: David Neto <dneto@google.com>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
|
||||
diff --git a/lib/HLSL/HLMatrixLowerPass.cpp b/lib/HLSL/HLMatrixLowerPass.cpp
|
||||
index e35ff832ecff9f2e46eecbd74f4b8b2f7cc7f700..c3a7254ef2b2f894a36ba8499b4aa9ace0afb8fa 100644
|
||||
--- a/lib/HLSL/HLMatrixLowerPass.cpp
|
||||
+++ b/lib/HLSL/HLMatrixLowerPass.cpp
|
||||
@@ -381,6 +381,11 @@ Value* HLMatrixLowerPass::getLoweredByValOperand(Value *Val, IRBuilder<> &Builde
|
||||
if (isa<ConstantAggregateZero>(Val))
|
||||
return ConstantAggregateZero::get(LoweredTy);
|
||||
|
||||
+ // Lower undef mat as undef vec
|
||||
+ if (isa<UndefValue>(Val)) {
|
||||
+ return UndefValue::get(LoweredTy);
|
||||
+ }
|
||||
+
|
||||
// Return a mat-to-vec translation stub
|
||||
FunctionType *TranslationStubTy = FunctionType::get(LoweredTy, { Ty }, /* isVarArg */ false);
|
||||
Function *TranslationStub = m_matToVecStubs->get(TranslationStubTy);
|
||||
@@ -2,3 +2,7 @@ m120_translator_optimize_field-name-collision_check.patch
|
||||
m120_translator_fail_compilation_if_too_many_struct_fields.patch
|
||||
m120_translator_limit_private_variable_size_to_64kb.patch
|
||||
m120_vulkan_don_t_crash_when_glcopyteximage2d_redefines_itself.patch
|
||||
m123_vulkan_fix_access_to_inactive_attributes.patch
|
||||
cherry-pick-f6672dbbe223.patch
|
||||
m119_move_invalid_uniform_protection_to_the_frontend.patch
|
||||
m120_fix_off-by-one_bounds_check_on_uniform_location.patch
|
||||
|
||||
267
patches/angle/cherry-pick-f6672dbbe223.patch
Normal file
267
patches/angle/cherry-pick-f6672dbbe223.patch
Normal file
@@ -0,0 +1,267 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 25 Mar 2024 14:46:56 -0400
|
||||
Subject: M123: Translator: Disallow samplers in structs in interface blocks
|
||||
|
||||
As disallowed by the spec:
|
||||
|
||||
> Types and declarators are the same as for other uniform variable
|
||||
> declarations outside blocks, with these exceptions:
|
||||
>
|
||||
> * opaque types are not allowed
|
||||
|
||||
Bug: chromium:328859176
|
||||
Change-Id: Ib94977860102329e520e635c3757827c93ca2163
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5391986
|
||||
Auto-Submit: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit a0fa06f6d79ced897c0fe2795551268199d29806)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5435737
|
||||
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
|
||||
|
||||
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
|
||||
index e174725beb764407185e471a9916ffd164493cd8..cb9eb3a4a566348f11aa5962037164147bc65684 100644
|
||||
--- a/src/compiler/translator/ParseContext.cpp
|
||||
+++ b/src/compiler/translator/ParseContext.cpp
|
||||
@@ -34,27 +34,39 @@ namespace
|
||||
|
||||
const int kWebGLMaxStructNesting = 4;
|
||||
|
||||
-bool ContainsSampler(const TStructure *structType);
|
||||
+struct IsSamplerFunc
|
||||
+{
|
||||
+ bool operator()(TBasicType type) { return IsSampler(type); }
|
||||
+};
|
||||
+struct IsOpaqueFunc
|
||||
+{
|
||||
+ bool operator()(TBasicType type) { return IsOpaqueType(type); }
|
||||
+};
|
||||
+
|
||||
+template <typename OpaqueFunc>
|
||||
+bool ContainsOpaque(const TStructure *structType);
|
||||
|
||||
-bool ContainsSampler(const TType &type)
|
||||
+template <typename OpaqueFunc>
|
||||
+bool ContainsOpaque(const TType &type)
|
||||
{
|
||||
- if (IsSampler(type.getBasicType()))
|
||||
+ if (OpaqueFunc{}(type.getBasicType()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (type.getBasicType() == EbtStruct)
|
||||
{
|
||||
- return ContainsSampler(type.getStruct());
|
||||
+ return ContainsOpaque<OpaqueFunc>(type.getStruct());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
-bool ContainsSampler(const TStructure *structType)
|
||||
+template <typename OpaqueFunc>
|
||||
+bool ContainsOpaque(const TStructure *structType)
|
||||
{
|
||||
for (const auto &field : structType->fields())
|
||||
{
|
||||
- if (ContainsSampler(*field->type()))
|
||||
+ if (ContainsOpaque<OpaqueFunc>(*field->type()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1057,7 +1069,7 @@ bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
|
||||
{
|
||||
if (pType.type == EbtStruct)
|
||||
{
|
||||
- if (ContainsSampler(pType.userDef))
|
||||
+ if (ContainsOpaque<IsSamplerFunc>(pType.userDef))
|
||||
{
|
||||
std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
|
||||
reasonStream << reason << " (structure contains a sampler)";
|
||||
@@ -4923,12 +4935,9 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
|
||||
{
|
||||
TField *field = (*fieldList)[memberIndex];
|
||||
TType *fieldType = field->type();
|
||||
- if (IsOpaqueType(fieldType->getBasicType()))
|
||||
+ if (ContainsOpaque<IsOpaqueFunc>(*fieldType))
|
||||
{
|
||||
- std::string reason("unsupported type - ");
|
||||
- reason += fieldType->getBasicString();
|
||||
- reason += " types are not allowed in interface blocks";
|
||||
- error(field->line(), reason.c_str(), fieldType->getBasicString());
|
||||
+ error(field->line(), "Opaque types are not allowed in interface blocks", blockName);
|
||||
}
|
||||
|
||||
const TQualifier qualifier = fieldType->getQualifier();
|
||||
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
|
||||
index f4b7ce6222ff4a29cb20b75bc102e2c8ae478189..8ac5b758b128ded933d727f7dccb0ce8f8eb338b 100644
|
||||
--- a/src/tests/gl_tests/GLSLTest.cpp
|
||||
+++ b/src/tests/gl_tests/GLSLTest.cpp
|
||||
@@ -6716,7 +6716,34 @@ void main()
|
||||
gl_FragColor = vec4(f(us), 0, 0, 1);
|
||||
})";
|
||||
|
||||
- CompileShader(GL_FRAGMENT_SHADER, kFS);
|
||||
+ GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
|
||||
+ EXPECT_NE(fs, 0u);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Test that structs with samplers are not allowed in interface blocks. This is forbidden per
|
||||
+// GLES3:
|
||||
+//
|
||||
+// > Types and declarators are the same as for other uniform variable declarations outside blocks,
|
||||
+// > with these exceptions:
|
||||
+// > * opaque types are not allowed
|
||||
+TEST_P(GLSLTest_ES3, StructWithSamplersDisallowedInInterfaceBlock)
|
||||
+{
|
||||
+ const char kFS[] = R"(#version 300 es
|
||||
+precision mediump float;
|
||||
+struct S { sampler2D samp; bool b; };
|
||||
+
|
||||
+layout(std140) uniform Buffer { S s; } buffer;
|
||||
+
|
||||
+out vec4 color;
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ color = texture(buffer.s.samp, vec2(0));
|
||||
+})";
|
||||
+
|
||||
+ GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
|
||||
+ EXPECT_EQ(fs, 0u);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
@@ -18195,6 +18222,116 @@ void main() {
|
||||
EXPECT_EQ(0u, shader);
|
||||
}
|
||||
|
||||
+// Same as TooManyFieldsInStruct, but with samplers in the struct.
|
||||
+TEST_P(GLSLTest_ES3, TooManySamplerFieldsInStruct)
|
||||
+{
|
||||
+ std::ostringstream fs;
|
||||
+ fs << R"(#version 300 es
|
||||
+precision highp float;
|
||||
+struct TooManyFields
|
||||
+{
|
||||
+)";
|
||||
+ for (uint32_t i = 0; i < (1 << 16); ++i)
|
||||
+ {
|
||||
+ fs << " sampler2D field" << i << ";\n";
|
||||
+ }
|
||||
+ fs << R"(};
|
||||
+uniform TooManyFields s;
|
||||
+out vec4 color;
|
||||
+void main() {
|
||||
+ color = texture(s.field0, vec2(0));
|
||||
+})";
|
||||
+
|
||||
+ GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
|
||||
+ EXPECT_EQ(0u, shader);
|
||||
+}
|
||||
+
|
||||
+// More complex variation of ManySamplerFieldsInStruct. This one compiles fine.
|
||||
+TEST_P(GLSLTest_ES3, ManySamplerFieldsInStructComplex)
|
||||
+{
|
||||
+ // D3D and OpenGL may be more restrictive about this many samplers.
|
||||
+ ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
|
||||
+
|
||||
+ std::ostringstream fs;
|
||||
+ fs << R"(#version 300 es
|
||||
+precision highp float;
|
||||
+
|
||||
+struct X {
|
||||
+ mediump sampler2D a[0xf00];
|
||||
+ mediump sampler2D b[0xf00];
|
||||
+ mediump sampler2D c[0xf000];
|
||||
+ mediump sampler2D d[0xf00];
|
||||
+};
|
||||
+
|
||||
+struct Y {
|
||||
+ X s1;
|
||||
+ mediump sampler2D a[0xf00];
|
||||
+ mediump sampler2D b[0xf000];
|
||||
+ mediump sampler2D c[0x14000];
|
||||
+};
|
||||
+
|
||||
+struct S {
|
||||
+ Y s1;
|
||||
+};
|
||||
+
|
||||
+struct structBuffer { S s; };
|
||||
+
|
||||
+uniform structBuffer b;
|
||||
+
|
||||
+out vec4 color;
|
||||
+void main()
|
||||
+{
|
||||
+ color = texture(b.s.s1.s1.c[0], vec2(0));
|
||||
+})";
|
||||
+
|
||||
+ GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
|
||||
+ EXPECT_NE(0u, shader);
|
||||
+}
|
||||
+
|
||||
+// Make sure a large array of samplers works.
|
||||
+TEST_P(GLSLTest, ManySamplers)
|
||||
+{
|
||||
+ // D3D and OpenGL may be more restrictive about this many samplers.
|
||||
+ ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
|
||||
+
|
||||
+ std::ostringstream fs;
|
||||
+ fs << R"(precision highp float;
|
||||
+
|
||||
+uniform mediump sampler2D c[0x12000];
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ gl_FragColor = texture2D(c[0], vec2(0));
|
||||
+})";
|
||||
+
|
||||
+ GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
|
||||
+ EXPECT_NE(0u, shader);
|
||||
+}
|
||||
+
|
||||
+// Make sure a large array of samplers works when declared in a struct.
|
||||
+TEST_P(GLSLTest, ManySamplersInStruct)
|
||||
+{
|
||||
+ // D3D and OpenGL may be more restrictive about this many samplers.
|
||||
+ ANGLE_SKIP_TEST_IF(IsD3D() || IsOpenGL());
|
||||
+
|
||||
+ std::ostringstream fs;
|
||||
+ fs << R"(precision highp float;
|
||||
+
|
||||
+struct X {
|
||||
+ mediump sampler2D c[0x12000];
|
||||
+};
|
||||
+
|
||||
+uniform X x;
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ gl_FragColor = texture2D(x.c[0], vec2(0));
|
||||
+})";
|
||||
+
|
||||
+ GLuint shader = CompileShader(GL_FRAGMENT_SHADER, fs.str().c_str());
|
||||
+ EXPECT_NE(0u, shader);
|
||||
+}
|
||||
+
|
||||
// Test that passing large arrays to functions are compiled correctly. Regression test for the
|
||||
// SPIR-V generator that made a copy of the array to pass to the function, by decomposing and
|
||||
// reconstructing it (in the absence of OpCopyLogical), but the reconstruction instruction has a
|
||||
diff --git a/src/tests/gl_tests/PixelLocalStorageTest.cpp b/src/tests/gl_tests/PixelLocalStorageTest.cpp
|
||||
index c49ba5741ad565ad9637fb2188a472ccbebc6284..126936271eb25eec601349a560fabc6f0f7d4b75 100644
|
||||
--- a/src/tests/gl_tests/PixelLocalStorageTest.cpp
|
||||
+++ b/src/tests/gl_tests/PixelLocalStorageTest.cpp
|
||||
@@ -5573,8 +5573,7 @@ TEST_P(PixelLocalStorageCompilerTest, Declarations)
|
||||
EXPECT_FALSE(log.compileFragmentShader(kPLSInStruct));
|
||||
EXPECT_TRUE(log.has("ERROR: 0:5: 'pixelLocalANGLE' : disallowed type in struct"));
|
||||
EXPECT_TRUE(
|
||||
- log.has("ERROR: 0:10: 'pixelLocalANGLE' : unsupported type - pixelLocalANGLE types are not "
|
||||
- "allowed in interface blocks"));
|
||||
+ log.has("ERROR: 0:10: 'PLSBlock' : Opaque types are not allowed in interface blocks"));
|
||||
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Tue, 17 Oct 2023 11:39:10 -0400
|
||||
Subject: M119: Move invalid uniform protection to the frontend.
|
||||
|
||||
The frontend potentialy indexes into mUniformLocations with invalid
|
||||
uniform locations while validation is disabled too. Move the validation
|
||||
from the Metal backend to the frontend.
|
||||
|
||||
Bug: chromium:1484878
|
||||
Change-Id: I92bc43aa28cfa26d601bb28f318860375f618608
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4947652
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit e076d6cfd0e1d6948623bb344c5a38753b0c2b2e)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4969232
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
|
||||
index 5caab257c909d81ea40c8bdad6bca8ce5e9c72c7..5dc66027831b0d1ac1915faf0d32223d6a71cd1c 100644
|
||||
--- a/src/libANGLE/Program.cpp
|
||||
+++ b/src/libANGLE/Program.cpp
|
||||
@@ -2192,7 +2192,7 @@ GLuint Program::getUniformIndex(const std::string &name) const
|
||||
|
||||
bool Program::shouldIgnoreUniform(UniformLocation location) const
|
||||
{
|
||||
- if (location.value == -1)
|
||||
+ if (location.value < 0 || static_cast<size_t>(location.value) >= mUniformLocations.size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
diff --git a/src/libANGLE/renderer/metal/ProgramMtl.mm b/src/libANGLE/renderer/metal/ProgramMtl.mm
|
||||
index 5b86c4a8e0fa00012460d2e14101494c1dc4fa82..c7b98020e47c2f881815685e122ecaa57dbc1ad9 100644
|
||||
--- a/src/libANGLE/renderer/metal/ProgramMtl.mm
|
||||
+++ b/src/libANGLE/renderer/metal/ProgramMtl.mm
|
||||
@@ -766,22 +766,10 @@ void operator()() override
|
||||
ProgramExecutableMtl *executableMtl = getExecutable();
|
||||
|
||||
const std::vector<gl::VariableLocation> &uniformLocations = mState.getUniformLocations();
|
||||
- if (location < 0 || static_cast<size_t>(location) >= uniformLocations.size())
|
||||
- {
|
||||
- ERR() << "Invalid uniform location " << location << ", expected [0, "
|
||||
- << uniformLocations.size() << ")";
|
||||
- return;
|
||||
- }
|
||||
- const gl::VariableLocation &locationInfo = uniformLocations[location];
|
||||
+ const gl::VariableLocation &locationInfo = uniformLocations[location];
|
||||
|
||||
const std::vector<gl::LinkedUniform> &linkedUniforms = mState.getUniforms();
|
||||
- if (locationInfo.index >= linkedUniforms.size())
|
||||
- {
|
||||
- ERR() << "Invalid uniform location index " << locationInfo.index << ", expected [0, "
|
||||
- << linkedUniforms.size() << ")";
|
||||
- return;
|
||||
- }
|
||||
- const gl::LinkedUniform &linkedUniform = linkedUniforms[locationInfo.index];
|
||||
+ const gl::LinkedUniform &linkedUniform = linkedUniforms[locationInfo.index];
|
||||
|
||||
if (linkedUniform.isSampler())
|
||||
{
|
||||
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Wed, 22 Nov 2023 12:01:31 -0500
|
||||
Subject: M120: Fix off-by-one bounds check on uniform location.
|
||||
|
||||
Log an error when the user provides an invalid uniform location.
|
||||
|
||||
Bug: chromium:1504162
|
||||
Bug: chromium:1484878
|
||||
Change-Id: Ieb7eb964d508954ac8dfa8e4d9bd941778185223
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5054238
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: James Godfrey-Kittle <jamesgk@google.com>
|
||||
(cherry picked from commit fba482b7107ccf3e178f6bf56b6b0285407ace3a)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5080772
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
|
||||
index 5dc66027831b0d1ac1915faf0d32223d6a71cd1c..d9e9582679b1e16e122c7e7b0a699e23cf45ae46 100644
|
||||
--- a/src/libANGLE/Program.cpp
|
||||
+++ b/src/libANGLE/Program.cpp
|
||||
@@ -2192,13 +2192,15 @@ GLuint Program::getUniformIndex(const std::string &name) const
|
||||
|
||||
bool Program::shouldIgnoreUniform(UniformLocation location) const
|
||||
{
|
||||
- if (location.value < 0 || static_cast<size_t>(location.value) >= mUniformLocations.size())
|
||||
+ if (location.value < 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
- if (mState.mExecutable->mUniformLocations[static_cast<size_t>(location.value)].ignored)
|
||||
+ if (static_cast<size_t>(location.value) >= mState.mExecutable->mUniformLocations.size())
|
||||
{
|
||||
+ ERR() << "Invalid uniform location " << location.value << ", expected [0, "
|
||||
+ << mState.mExecutable->mUniformLocations.size() << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Tue, 12 Mar 2024 16:06:37 -0400
|
||||
Subject: M123: Vulkan: Fix access to inactive attributes
|
||||
|
||||
... within range of active ones. Since a buffer is bound for inactive
|
||||
attributes, it must be considered accessed.
|
||||
|
||||
Ultimately, the nullDescriptor feature could be used to avoid binding a
|
||||
buffer for inactive attributes.
|
||||
|
||||
Bug: chromium:327807820
|
||||
Change-Id: I953b419d8ec51760e8848409024cad5083888fa2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5386431
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
index 9965bb1084ea237a18f72a1549916c0a6140806e..8e1708c82cd97acee56aae131c7d629c05a9d6a9 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
@@ -2596,8 +2596,7 @@ angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *d
|
||||
vertexArrayVk->getCurrentArrayBuffers();
|
||||
|
||||
// Mark all active vertex buffers as accessed.
|
||||
- const gl::AttributesMask attribsMask = executable->getActiveAttribLocationsMask();
|
||||
- for (size_t attribIndex : attribsMask)
|
||||
+ for (uint32_t attribIndex = 0; attribIndex < maxAttrib; ++attribIndex)
|
||||
{
|
||||
vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
|
||||
if (arrayBuffer)
|
||||
diff --git a/src/tests/gl_tests/VertexAttributeTest.cpp b/src/tests/gl_tests/VertexAttributeTest.cpp
|
||||
index b26821200e472bec3d522d7b3e7f7aa0cb0d27a5..c37868cd4067aced75f2edb7397d72457a6fabb3 100644
|
||||
--- a/src/tests/gl_tests/VertexAttributeTest.cpp
|
||||
+++ b/src/tests/gl_tests/VertexAttributeTest.cpp
|
||||
@@ -1200,6 +1200,19 @@ class VertexAttributeOORTest : public VertexAttributeTest
|
||||
}
|
||||
};
|
||||
|
||||
+class RobustVertexAttributeTest : public VertexAttributeTest
|
||||
+{
|
||||
+ public:
|
||||
+ RobustVertexAttributeTest()
|
||||
+ {
|
||||
+ // mac GL and metal do not support robustness.
|
||||
+ if (!IsMac() && !IsIOS())
|
||||
+ {
|
||||
+ setRobustAccess(true);
|
||||
+ }
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
// Verify that drawing with a large out-of-range offset generates INVALID_OPERATION.
|
||||
// Requires WebGL compatibility with robust access behaviour disabled.
|
||||
TEST_P(VertexAttributeOORTest, ANGLEDrawArraysBufferTooSmall)
|
||||
@@ -1260,6 +1273,48 @@ TEST_P(VertexAttributeOORTest, ANGLEDrawArraysOutOfBoundsCases)
|
||||
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
+// Test that enabling a buffer in an unused attribute doesn't crash. There should be an active
|
||||
+// attribute after that.
|
||||
+TEST_P(RobustVertexAttributeTest, BoundButUnusedBuffer)
|
||||
+{
|
||||
+ constexpr char kVS[] = R"(attribute vec2 offset;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(offset.xy, 0, 1);
|
||||
+ gl_PointSize = 1.0;
|
||||
+})";
|
||||
+
|
||||
+ constexpr char kFS[] = R"(precision mediump float;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_FragColor = vec4(1.0, 0, 0, 1.0);
|
||||
+})";
|
||||
+
|
||||
+ const GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
|
||||
+ const GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
|
||||
+
|
||||
+ GLuint program = glCreateProgram();
|
||||
+ glBindAttribLocation(program, 1, "offset");
|
||||
+ glAttachShader(program, vs);
|
||||
+ glAttachShader(program, fs);
|
||||
+ glLinkProgram(program);
|
||||
+
|
||||
+ GLBuffer buffer;
|
||||
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
+ glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_STATIC_DRAW);
|
||||
+
|
||||
+ // Enable an unused attribute that is within the range of active attributes (not beyond it)
|
||||
+ glEnableVertexAttribArray(0);
|
||||
+ glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
|
||||
+
|
||||
+ glUseProgram(program);
|
||||
+ glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
+
|
||||
+ // Destroy the buffer. Regression test for a tracking bug where the buffer was used by
|
||||
+ // SwiftShader (even though location 1 is inactive), but not marked as used by ANGLE.
|
||||
+ buffer.reset();
|
||||
+}
|
||||
+
|
||||
// Verify that using a different start vertex doesn't mess up the draw.
|
||||
TEST_P(VertexAttributeTest, DrawArraysWithBufferOffset)
|
||||
{
|
||||
@@ -4544,6 +4599,8 @@ ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
|
||||
ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
|
||||
ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass));
|
||||
|
||||
+ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(RobustVertexAttributeTest);
|
||||
+
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES3);
|
||||
ANGLE_INSTANTIATE_TEST_ES3_AND(
|
||||
VertexAttributeTestES3,
|
||||
@@ -150,3 +150,17 @@ reland_mojom_ts_generator_handle_empty_module_path_identically_to.patch
|
||||
cherry-pick-c1cda70a433a.patch
|
||||
cherry-pick-cc07a95bc309.patch
|
||||
safely_crash_on_dangling_profile.patch
|
||||
cherry-pick-91a02d67a83d.patch
|
||||
cherry-pick-8755f76bec32.patch
|
||||
cherry-pick-1f8bec968902.patch
|
||||
cherry-pick-4a98f9e304be.patch
|
||||
fix_racy_iterator_use_in_node_addconnection.patch
|
||||
fix_a_crash_when_a_bmp_image_contains_an_unnecessary_eof_code.patch
|
||||
m120_ipcz_fix_a_few_weak_asserts.patch
|
||||
prevent_mojotrap_event_re-ordering.patch
|
||||
m122_cherry_pick_cve-2024-25062_libxml_fix.patch
|
||||
update_crashpad_to_37afd37401253ebcebcf6e07ce15c8cfecb1a1cc.patch
|
||||
m122_webcodecs_disable_async_videoframe_readback_to_mitigate_a.patch
|
||||
fix_paintimage_deserialization_arbitrary-read_issue.patch
|
||||
reland_sensors_winrt_call_onreadingchangedcallback_via.patch
|
||||
cherry-pick-1b1f34234346.patch
|
||||
|
||||
42
patches/chromium/cherry-pick-1b1f34234346.patch
Normal file
42
patches/chromium/cherry-pick-1b1f34234346.patch
Normal file
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kylechar <kylechar@chromium.org>
|
||||
Date: Tue, 9 Apr 2024 17:14:26 +0000
|
||||
Subject: Validate buffer length
|
||||
|
||||
The BitmapInSharedMemory mojo traits were only validating row length and
|
||||
not total buffer length.
|
||||
|
||||
(cherry picked from commit 1a19ff70bd54847d818566bd7a1e7c384c419746)
|
||||
|
||||
(cherry picked from commit f15315f1cb7897e208947a40d538aac693283d7f)
|
||||
|
||||
Bug: 331237485
|
||||
Change-Id: Ia2318899c44e9e7ac72fc7183954e6ce2c702179
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5396796
|
||||
Commit-Queue: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/main@{#1278417}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5420432
|
||||
Commit-Queue: danakj <danakj@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/6312@{#786}
|
||||
Cr-Original-Branched-From: 6711dcdae48edaf98cbc6964f90fac85b7d9986e-refs/heads/main@{#1262506}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5433678
|
||||
Reviewed-by: danakj <danakj@chromium.org>
|
||||
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#2003}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/services/viz/public/cpp/compositing/bitmap_in_shared_memory_mojom_traits.cc b/services/viz/public/cpp/compositing/bitmap_in_shared_memory_mojom_traits.cc
|
||||
index a6e5f45d9e72b9ac48e536c3a7756966b3c263cf..519d554055e5182cdcbae44fafdac339a64a923b 100644
|
||||
--- a/services/viz/public/cpp/compositing/bitmap_in_shared_memory_mojom_traits.cc
|
||||
+++ b/services/viz/public/cpp/compositing/bitmap_in_shared_memory_mojom_traits.cc
|
||||
@@ -76,6 +76,10 @@ bool StructTraits<viz::mojom::BitmapInSharedMemoryDataView, SkBitmap>::Read(
|
||||
if (!mapping_ptr->IsValid())
|
||||
return false;
|
||||
|
||||
+ if (mapping_ptr->size() < image_info.computeByteSize(data.row_bytes())) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
if (!sk_bitmap->installPixels(image_info, mapping_ptr->memory(),
|
||||
data.row_bytes(), &DeleteSharedMemoryMapping,
|
||||
mapping_ptr.get())) {
|
||||
125
patches/chromium/cherry-pick-1f8bec968902.patch
Normal file
125
patches/chromium/cherry-pick-1f8bec968902.patch
Normal file
@@ -0,0 +1,125 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tsuyoshi Horo <horo@chromium.org>
|
||||
Date: Wed, 24 Jan 2024 02:04:24 +0000
|
||||
Subject: Fix UAF in SourceStreamToDataPipe
|
||||
|
||||
SourceStreamToDataPipe::ReadMore() is passing a callback with
|
||||
Unretained(this) to net::SourceStream::Read(). But this callback may be
|
||||
called even after the SourceStream is destructed. This is causing UAF
|
||||
issue (crbug.com/1511085).
|
||||
|
||||
To solve this problem, this CL changes ReadMore() method to pass a
|
||||
callback with a weak ptr of this.
|
||||
|
||||
(cherry picked from commit 6e36a69da1b73f9aea9c54bfbe6c5b9cb2c672a5)
|
||||
|
||||
Bug: 1511085
|
||||
Change-Id: Idd4e34ff300ff5db2de1de7b303841c7db3a964a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5179746
|
||||
Reviewed-by: Adam Rice <ricea@chromium.org>
|
||||
Commit-Queue: Tsuyoshi Horo <horo@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1244526}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5231558
|
||||
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1860}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/services/network/public/cpp/source_stream_to_data_pipe.cc b/services/network/public/cpp/source_stream_to_data_pipe.cc
|
||||
index bfd85b1a00b216b52ae816ca29cb66ddabe20b6d..07afd58a40f92485ded07c535092a891c5140c7b 100644
|
||||
--- a/services/network/public/cpp/source_stream_to_data_pipe.cc
|
||||
+++ b/services/network/public/cpp/source_stream_to_data_pipe.cc
|
||||
@@ -55,9 +55,9 @@ void SourceStreamToDataPipe::ReadMore() {
|
||||
|
||||
scoped_refptr<net::IOBuffer> buffer(
|
||||
new network::NetToMojoIOBuffer(pending_write_.get()));
|
||||
- int result = source_->Read(
|
||||
- buffer.get(), base::checked_cast<int>(num_bytes),
|
||||
- base::BindOnce(&SourceStreamToDataPipe::DidRead, base::Unretained(this)));
|
||||
+ int result = source_->Read(buffer.get(), base::checked_cast<int>(num_bytes),
|
||||
+ base::BindOnce(&SourceStreamToDataPipe::DidRead,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
|
||||
if (result != net::ERR_IO_PENDING)
|
||||
DidRead(result);
|
||||
diff --git a/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc b/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
|
||||
index 7061418c5141d936f04b1193c98e66efc5e72ac5..54159df39afa7cf6e2faa51da185dc034b923209 100644
|
||||
--- a/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
|
||||
+++ b/services/network/public/cpp/source_stream_to_data_pipe_unittest.cc
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
+#include "base/test/bind.h"
|
||||
#include "base/test/task_environment.h"
|
||||
+#include "net/base/net_errors.h"
|
||||
#include "net/filter/mock_source_stream.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
@@ -42,6 +44,33 @@ struct SourceStreamToDataPipeTestParam {
|
||||
const ReadResultType read_result_type;
|
||||
};
|
||||
|
||||
+class DummyPendingSourceStream : public net::SourceStream {
|
||||
+ public:
|
||||
+ DummyPendingSourceStream() : net::SourceStream(SourceStream::TYPE_NONE) {}
|
||||
+ ~DummyPendingSourceStream() override = default;
|
||||
+
|
||||
+ DummyPendingSourceStream(const DummyPendingSourceStream&) = delete;
|
||||
+ DummyPendingSourceStream& operator=(const DummyPendingSourceStream&) = delete;
|
||||
+
|
||||
+ // SourceStream implementation
|
||||
+ int Read(net::IOBuffer* dest_buffer,
|
||||
+ int buffer_size,
|
||||
+ net::CompletionOnceCallback callback) override {
|
||||
+ callback_ = std::move(callback);
|
||||
+ return net::ERR_IO_PENDING;
|
||||
+ }
|
||||
+ std::string Description() const override { return ""; }
|
||||
+ bool MayHaveMoreBytes() const override { return true; }
|
||||
+
|
||||
+ net::CompletionOnceCallback TakeCompletionCallback() {
|
||||
+ CHECK(callback_);
|
||||
+ return std::move(callback_);
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ net::CompletionOnceCallback callback_;
|
||||
+};
|
||||
+
|
||||
} // namespace
|
||||
|
||||
class SourceStreamToDataPipeTest
|
||||
@@ -212,4 +241,33 @@ TEST_P(SourceStreamToDataPipeTest, MayHaveMoreBytes) {
|
||||
EXPECT_EQ(ReadPipe(&output), net::OK);
|
||||
EXPECT_EQ(output, message);
|
||||
}
|
||||
+
|
||||
+TEST(SourceStreamToDataPipeCallbackTest, CompletionCallbackAfterDestructed) {
|
||||
+ base::test::TaskEnvironment task_environment;
|
||||
+
|
||||
+ std::unique_ptr<DummyPendingSourceStream> source =
|
||||
+ std::make_unique<DummyPendingSourceStream>();
|
||||
+ DummyPendingSourceStream* source_ptr = source.get();
|
||||
+ const MojoCreateDataPipeOptions data_pipe_options{
|
||||
+ sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 1};
|
||||
+ mojo::ScopedDataPipeProducerHandle producer_end;
|
||||
+ mojo::ScopedDataPipeConsumerHandle consumer_end;
|
||||
+ CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&data_pipe_options,
|
||||
+ producer_end, consumer_end));
|
||||
+
|
||||
+ std::unique_ptr<SourceStreamToDataPipe> adapter =
|
||||
+ std::make_unique<SourceStreamToDataPipe>(std::move(source),
|
||||
+ std::move(producer_end));
|
||||
+ bool callback_called = false;
|
||||
+ adapter->Start(
|
||||
+ base::BindLambdaForTesting([&](int result) { callback_called = true; }));
|
||||
+ net::CompletionOnceCallback callback = source_ptr->TakeCompletionCallback();
|
||||
+ adapter.reset();
|
||||
+
|
||||
+ // Test that calling `callback` after deleting `adapter` must not cause UAF
|
||||
+ // (crbug.com/1511085).
|
||||
+ std::move(callback).Run(net::ERR_FAILED);
|
||||
+ EXPECT_FALSE(callback_called);
|
||||
+}
|
||||
+
|
||||
} // namespace network
|
||||
67
patches/chromium/cherry-pick-4a98f9e304be.patch
Normal file
67
patches/chromium/cherry-pick-4a98f9e304be.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Peter=20Bostr=C3=B6m?= <pbos@chromium.org>
|
||||
Date: Fri, 26 Jan 2024 19:37:57 +0000
|
||||
Subject: Speculatively fix race in mojo ShutDownOnIOThread
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This acquires `write_lock_` before resetting handles used by WriteNoLock
|
||||
(which is called under the same lock in another thread). We also set
|
||||
`reject_writes_` to prevent future write attempts after shutdown. That
|
||||
seems strictly more correct.
|
||||
|
||||
We also acquire `fds_to_close_lock_` before clearing the FDs.
|
||||
|
||||
I was unable to repro locally as content_browsertests just times out
|
||||
in my local setup without reporting anything interesting. This seems
|
||||
strictly more correct though.
|
||||
|
||||
(cherry picked from commit 9755d9d81e4a8cb5b4f76b23b761457479dbb06b)
|
||||
|
||||
Bug: 1519980
|
||||
Change-Id: I96279936ca908ecb98eddd381df20d61597cba43
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5226127
|
||||
Auto-Submit: Peter Boström <pbos@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Peter Boström <pbos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1250580}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5239564
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1883}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/mojo/core/channel_posix.cc b/mojo/core/channel_posix.cc
|
||||
index 0a3596382d0e9a40c72bfb4ead6f0338a61253d6..eae6b0768463679b5043514dc5745da52b80ae10 100644
|
||||
--- a/mojo/core/channel_posix.cc
|
||||
+++ b/mojo/core/channel_posix.cc
|
||||
@@ -246,16 +246,21 @@ void ChannelPosix::WaitForWriteOnIOThreadNoLock() {
|
||||
void ChannelPosix::ShutDownOnIOThread() {
|
||||
base::CurrentThread::Get()->RemoveDestructionObserver(this);
|
||||
|
||||
- read_watcher_.reset();
|
||||
- write_watcher_.reset();
|
||||
- if (leak_handle_) {
|
||||
- std::ignore = socket_.release();
|
||||
- } else {
|
||||
- socket_.reset();
|
||||
- }
|
||||
+ {
|
||||
+ base::AutoLock lock(write_lock_);
|
||||
+ reject_writes_ = true;
|
||||
+ read_watcher_.reset();
|
||||
+ write_watcher_.reset();
|
||||
+ if (leak_handle_) {
|
||||
+ std::ignore = socket_.release();
|
||||
+ } else {
|
||||
+ socket_.reset();
|
||||
+ }
|
||||
#if BUILDFLAG(IS_IOS)
|
||||
- fds_to_close_.clear();
|
||||
+ base::AutoLock fd_lock(fds_to_close_lock_);
|
||||
+ fds_to_close_.clear();
|
||||
#endif
|
||||
+ }
|
||||
|
||||
// May destroy the |this| if it was the last reference.
|
||||
self_ = nullptr;
|
||||
110
patches/chromium/cherry-pick-8755f76bec32.patch
Normal file
110
patches/chromium/cherry-pick-8755f76bec32.patch
Normal file
@@ -0,0 +1,110 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Guido Urdaneta <guidou@chromium.org>
|
||||
Date: Thu, 18 Jan 2024 16:47:18 +0000
|
||||
Subject: Exit early from RTCPeerConnectionHandler
|
||||
|
||||
For certain operations that require a live client
|
||||
(i.e., RTCPeerConnection, which is garbage collected),
|
||||
PeerConnectionHandler keeps a pointer to the client on the stack
|
||||
to prevent garbage collection.
|
||||
|
||||
In some cases, the client may have already been garbage collected
|
||||
(the client is null). In that case, there is no point in doing the
|
||||
operation and it should exit early to avoid UAF/crashes.
|
||||
|
||||
This CL adds early exit to the cases that do not already have it.
|
||||
|
||||
Bug: 1514777
|
||||
Change-Id: I27e9541cfaa74d978799c03e2832a0980f9e5710
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5210359
|
||||
Reviewed-by: Tomas Gunnarsson <tommi@chromium.org>
|
||||
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1248826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
index 473eb82685f004d960f3d488e3976a2305eda248..b6d893cc0f93d5bbb12b07734c63b31a52d662f1 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
@@ -1056,15 +1056,19 @@ bool RTCPeerConnectionHandler::Initialize(
|
||||
WebLocalFrame* frame,
|
||||
ExceptionState& exception_state) {
|
||||
DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
- DCHECK(frame);
|
||||
DCHECK(dependency_factory_);
|
||||
- frame_ = frame;
|
||||
|
||||
CHECK(!initialize_called_);
|
||||
initialize_called_ = true;
|
||||
|
||||
// Prevent garbage collection of client_ during processing.
|
||||
auto* client_on_stack = client_.Get();
|
||||
+ if (!client_on_stack) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ DCHECK(frame);
|
||||
+ frame_ = frame;
|
||||
peer_connection_tracker_ = PeerConnectionTracker::From(*frame);
|
||||
|
||||
configuration_ = server_configuration;
|
||||
@@ -2312,10 +2316,13 @@ void RTCPeerConnectionHandler::OnIceCandidate(const String& sdp,
|
||||
int sdp_mline_index,
|
||||
int component,
|
||||
int address_family) {
|
||||
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
// In order to ensure that the RTCPeerConnection is not garbage collected
|
||||
// from under the function, we keep a pointer to it on the stack.
|
||||
auto* client_on_stack = client_.Get();
|
||||
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ if (!client_on_stack) {
|
||||
+ return;
|
||||
+ }
|
||||
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
|
||||
// This line can cause garbage collection.
|
||||
auto* platform_candidate = MakeGarbageCollected<RTCIceCandidatePlatform>(
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
|
||||
index f8838ab0c5a31182e210cc6f42b9f489c7dd5365..f689a679a7589f16839349189cbfdf84efd14367 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler_test.cc
|
||||
@@ -601,7 +601,7 @@ class RTCPeerConnectionHandlerTest : public SimTest {
|
||||
waitable_event->Signal();
|
||||
}
|
||||
|
||||
- public:
|
||||
+ protected:
|
||||
ScopedTestingPlatformSupport<AudioCapturerSourceTestingPlatformSupport>
|
||||
webrtc_audio_device_platform_support_;
|
||||
Persistent<MockRTCPeerConnectionHandlerClient> mock_client_;
|
||||
@@ -1168,4 +1168,32 @@ TEST_F(RTCPeerConnectionHandlerTest,
|
||||
observer->OnIceCandidate(native_candidate.get());
|
||||
}
|
||||
|
||||
+TEST_F(RTCPeerConnectionHandlerTest,
|
||||
+ OnIceCandidateAfterClientGarbageCollectionDoesNothing) {
|
||||
+ testing::InSequence sequence;
|
||||
+ EXPECT_CALL(*mock_tracker_.Get(),
|
||||
+ TrackAddIceCandidate(pc_handler_.get(), _,
|
||||
+ PeerConnectionTracker::kSourceLocal, true))
|
||||
+ .Times(0);
|
||||
+
|
||||
+ std::unique_ptr<webrtc::IceCandidateInterface> native_candidate(
|
||||
+ mock_dependency_factory_->CreateIceCandidate("sdpMid", 1, kDummySdp));
|
||||
+ mock_client_ = nullptr;
|
||||
+ WebHeap::CollectAllGarbageForTesting();
|
||||
+ pc_handler_->observer()->OnIceCandidate(native_candidate.get());
|
||||
+ RunMessageLoopsUntilIdle();
|
||||
+}
|
||||
+
|
||||
+TEST_F(RTCPeerConnectionHandlerTest,
|
||||
+ OnIceCandidateAfterClientGarbageCollectionFails) {
|
||||
+ DummyExceptionStateForTesting exception_state;
|
||||
+ auto pc_handler = CreateRTCPeerConnectionHandlerUnderTest();
|
||||
+ mock_client_ = nullptr;
|
||||
+ WebHeap::CollectAllGarbageForTesting();
|
||||
+ EXPECT_FALSE(pc_handler->Initialize(
|
||||
+ /*context=*/nullptr, webrtc::PeerConnectionInterface::RTCConfiguration(),
|
||||
+ /*media_constraints=*/nullptr,
|
||||
+ /*frame=*/nullptr, exception_state));
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
125
patches/chromium/cherry-pick-91a02d67a83d.patch
Normal file
125
patches/chromium/cherry-pick-91a02d67a83d.patch
Normal file
@@ -0,0 +1,125 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jean-Philippe Gravel <jpgravel@chromium.org>
|
||||
Date: Tue, 23 Jan 2024 21:37:50 +0000
|
||||
Subject: Fix use-after-free in DrawTextInternal
|
||||
|
||||
DrawTextInternal was calling GetOrCreatePaintCanvas multiple times,
|
||||
once at the start of the function, once inside of the
|
||||
BaseRenderingContext2DAutoRestoreSkCanvas helper class and once in the
|
||||
Draw call. GetOrCreatePaintCanvas destroys the canvas resource provider
|
||||
if the GPU context is lost. If this happens on the second call to
|
||||
GetOrCreatePaintCanvas, destroying the resource provider will
|
||||
invalidate the cc::PaintCanvas returned by the first call to
|
||||
GetOrCreatePaintCanvas.
|
||||
|
||||
The GPU process can technically crash at any point during the renderer
|
||||
process execution (perhaps because of something another renderer
|
||||
process did). We therefore have to assume that any call to
|
||||
GetOrCreatePaintCanvas can invalidate previously returned
|
||||
cc::PaintCanvas.
|
||||
|
||||
(cherry picked from commit d4a197e4913f8e5072263b59aedc29f2b5af3e93)
|
||||
|
||||
Change-Id: Ifa77735ab1b2b55b3d494f886b8566299937f6fe
|
||||
Fixed: 1511567
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5198419
|
||||
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
|
||||
Commit-Queue: Jean-Philippe Gravel <jpgravel@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1248204}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5230237
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1859}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
|
||||
index f09459b0b67c37d307c70a516731d05db49f49b8..89cb2a41b3eef8bb359984b0d14bfa0e4e19cfdc 100644
|
||||
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
|
||||
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
|
||||
@@ -2682,40 +2682,6 @@ const Font& BaseRenderingContext2D::AccessFont(HTMLCanvasElement* canvas) {
|
||||
return GetState().GetFont();
|
||||
}
|
||||
|
||||
-namespace {
|
||||
-
|
||||
-// Drawing methods need to use this instead of SkAutoCanvasRestore in case
|
||||
-// overdraw detection substitutes the recording canvas (to discard overdrawn
|
||||
-// draw calls).
|
||||
-class BaseRenderingContext2DAutoRestoreSkCanvas {
|
||||
- STACK_ALLOCATED();
|
||||
-
|
||||
- public:
|
||||
- explicit BaseRenderingContext2DAutoRestoreSkCanvas(
|
||||
- BaseRenderingContext2D* context)
|
||||
- : context_(context) {
|
||||
- DCHECK(context_);
|
||||
- cc::PaintCanvas* c = context_->GetOrCreatePaintCanvas();
|
||||
- if (c) {
|
||||
- save_count_ = c->getSaveCount();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- ~BaseRenderingContext2DAutoRestoreSkCanvas() {
|
||||
- cc::PaintCanvas* c = context_->GetOrCreatePaintCanvas();
|
||||
- if (c) {
|
||||
- c->restoreToCount(save_count_);
|
||||
- }
|
||||
- context_->ValidateStateStack();
|
||||
- }
|
||||
-
|
||||
- private:
|
||||
- BaseRenderingContext2D* context_;
|
||||
- int save_count_ = 0;
|
||||
-};
|
||||
-
|
||||
-} // namespace
|
||||
-
|
||||
void BaseRenderingContext2D::DrawTextInternal(
|
||||
const String& text,
|
||||
double x,
|
||||
@@ -2736,8 +2702,10 @@ void BaseRenderingContext2D::DrawTextInternal(
|
||||
canvas->GetDocument().UpdateStyleAndLayoutTreeForNode(
|
||||
canvas, DocumentUpdateReason::kCanvas);
|
||||
}
|
||||
- cc::PaintCanvas* c = GetOrCreatePaintCanvas();
|
||||
- if (!c) {
|
||||
+
|
||||
+ // Abort if we don't have a paint canvas (e.g. the context was lost).
|
||||
+ cc::PaintCanvas* paint_canvas = GetOrCreatePaintCanvas();
|
||||
+ if (!paint_canvas) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2808,14 +2776,13 @@ void BaseRenderingContext2D::DrawTextInternal(
|
||||
InflateStrokeRect(bounds);
|
||||
}
|
||||
|
||||
- BaseRenderingContext2DAutoRestoreSkCanvas state_restorer(this);
|
||||
if (use_max_width) {
|
||||
- c->save();
|
||||
+ paint_canvas->save();
|
||||
// We draw when fontWidth is 0 so compositing operations (eg, a "copy" op)
|
||||
// still work. As the width of canvas is scaled, so text can be scaled to
|
||||
// match the given maxwidth, update text location so it appears on desired
|
||||
// place.
|
||||
- c->scale(ClampTo<float>(width / font_width), 1);
|
||||
+ paint_canvas->scale(ClampTo<float>(width / font_width), 1);
|
||||
location.set_x(location.x() / ClampTo<float>(width / font_width));
|
||||
}
|
||||
|
||||
@@ -2846,6 +2813,16 @@ void BaseRenderingContext2D::DrawTextInternal(
|
||||
{ return false; },
|
||||
bounds, paint_type, CanvasRenderingContext2DState::kNoImage,
|
||||
CanvasPerformanceMonitor::DrawType::kText);
|
||||
+
|
||||
+ if (use_max_width) {
|
||||
+ // Cannot use `paint_canvas` in case recording canvas was substituted or
|
||||
+ // destroyed during draw call.
|
||||
+ cc::PaintCanvas* c = GetPaintCanvas();
|
||||
+ if (c) {
|
||||
+ c->restore();
|
||||
+ }
|
||||
+ }
|
||||
+ ValidateStateStack();
|
||||
}
|
||||
|
||||
TextMetrics* BaseRenderingContext2D::measureText(const String& text) {
|
||||
@@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Stiles <johnstiles@google.com>
|
||||
Date: Thu, 1 Feb 2024 20:40:55 +0000
|
||||
Subject: Fix a crash when a BMP image contains an unnecessary EOF code.
|
||||
|
||||
Previously, this would try to perform color correction on a row
|
||||
one past the end of the image data.
|
||||
|
||||
(cherry picked from commit 4bdd8d61bebbba9fab77fa86a8f66b305995199b)
|
||||
|
||||
Bug: 1521893
|
||||
Change-Id: I425437005b9ef400138556705616095857d2cf0d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5241305
|
||||
Auto-Submit: John Stiles <johnstiles@google.com>
|
||||
Commit-Queue: John Stiles <johnstiles@google.com>
|
||||
Reviewed-by: Peter Kasting <pkasting@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1253633}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5259699
|
||||
Commit-Queue: Peter Kasting <pkasting@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1915}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
|
||||
index 42d0414da143f509a89551c8b09762949f8011c2..49e238e38fef374c698fcdc1d4b50d4ed7670c3d 100644
|
||||
--- a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
|
||||
+++ b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
|
||||
@@ -403,6 +403,7 @@
|
||||
../../web_tests/images/resources/truncated.webp
|
||||
../../web_tests/images/resources/truncated2.webp
|
||||
../../web_tests/images/resources/twitter_favicon.ico
|
||||
+../../web_tests/images/resources/unnecessary-eof.bmp
|
||||
../../web_tests/images/resources/webp-animated-icc-xmp.webp
|
||||
../../web_tests/images/resources/webp-animated-large.webp
|
||||
../../web_tests/images/resources/webp-animated-no-blend.webp
|
||||
diff --git a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc
|
||||
index 85e3591ac707297944b81cc4673b75d308417bd1..6c867a76a44c57ae818e7a00df30d046077b4d4c 100644
|
||||
--- a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc
|
||||
+++ b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder_test.cc
|
||||
@@ -98,6 +98,19 @@ TEST(BMPImageDecoderTest, crbug752898) {
|
||||
decoder->DecodeFrameBufferAtIndex(0);
|
||||
}
|
||||
|
||||
+// Verify that decoding an image with an unnecessary EOF marker does not crash.
|
||||
+TEST(BMPImageDecoderTest, allowEOFWhenPastEndOfImage) {
|
||||
+ static constexpr char kBmpFile[] = "/images/resources/unnecessary-eof.bmp";
|
||||
+ scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile);
|
||||
+ ASSERT_TRUE(data.get());
|
||||
+
|
||||
+ std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
|
||||
+ decoder->SetData(data.get(), true);
|
||||
+ ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
|
||||
+ EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
|
||||
+ EXPECT_FALSE(decoder->Failed());
|
||||
+}
|
||||
+
|
||||
class BMPImageDecoderCorpusTest : public ImageDecoderBaseTest {
|
||||
public:
|
||||
BMPImageDecoderCorpusTest() : ImageDecoderBaseTest("bmp") {}
|
||||
diff --git a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
|
||||
index 6b6bcb2e8fce05062e80b84283fd635f9d4bf008..b7bbbf51a1b419d1641db5e2f062cfefb2eae554 100644
|
||||
--- a/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
|
||||
+++ b/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc
|
||||
@@ -886,7 +886,8 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessRLEData() {
|
||||
// the image.
|
||||
const uint8_t count = ReadUint8(0);
|
||||
const uint8_t code = ReadUint8(1);
|
||||
- if ((count || (code != 1)) && PastEndOfImage(0)) {
|
||||
+ const bool is_past_end_of_image = PastEndOfImage(0);
|
||||
+ if ((count || (code != 1)) && is_past_end_of_image) {
|
||||
return kFailure;
|
||||
}
|
||||
|
||||
@@ -911,7 +912,9 @@ BMPImageReader::ProcessingResult BMPImageReader::ProcessRLEData() {
|
||||
: (coord_.y() > 0))) {
|
||||
buffer_->SetHasAlpha(true);
|
||||
}
|
||||
- ColorCorrectCurrentRow();
|
||||
+ if (!is_past_end_of_image) {
|
||||
+ ColorCorrectCurrentRow();
|
||||
+ }
|
||||
// There's no need to move |coord_| here to trigger the caller
|
||||
// to call SetPixelsChanged(). If the only thing that's changed
|
||||
// is the alpha state, that will be properly written into the
|
||||
@@ -1136,6 +1139,13 @@ void BMPImageReader::ColorCorrectCurrentRow() {
|
||||
if (!transform) {
|
||||
return;
|
||||
}
|
||||
+ int decoder_width = parent_->Size().width();
|
||||
+ // Enforce 0 ≤ current row < bitmap height.
|
||||
+ CHECK_GE(coord_.y(), 0);
|
||||
+ CHECK_LT(coord_.y(), buffer_->Bitmap().height());
|
||||
+ // Enforce decoder width == bitmap width exactly. (The bitmap rowbytes might
|
||||
+ // add a bit of padding, but we are only converting one row at a time.)
|
||||
+ CHECK_EQ(decoder_width, buffer_->Bitmap().width());
|
||||
ImageFrame::PixelData* const row = buffer_->GetAddr(0, coord_.y());
|
||||
const skcms_PixelFormat fmt = XformColorFormat();
|
||||
const skcms_AlphaFormat alpha =
|
||||
@@ -1144,7 +1154,7 @@ void BMPImageReader::ColorCorrectCurrentRow() {
|
||||
: skcms_AlphaFormat_Unpremul;
|
||||
const bool success =
|
||||
skcms_Transform(row, fmt, alpha, transform->SrcProfile(), row, fmt, alpha,
|
||||
- transform->DstProfile(), parent_->Size().width());
|
||||
+ transform->DstProfile(), decoder_width);
|
||||
DCHECK(success);
|
||||
buffer_->SetPixelsChanged(true);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peng Huang <penghuang@chromium.org>
|
||||
Date: Wed, 20 Mar 2024 16:22:16 +0000
|
||||
Subject: Fix PaintImage deserialization arbitrary-read issue
|
||||
|
||||
(cherry picked from commit 47e8386c97ac7a84a96866fbd35422b99a01de5a)
|
||||
|
||||
Bug: 327183408
|
||||
Change-Id: I09927fbae60b666aaa370e3aba01607cdb977a25
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5370455
|
||||
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
|
||||
Commit-Queue: Peng Huang <penghuang@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1272930}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5382202
|
||||
Auto-Submit: Peng Huang <penghuang@chromium.org>
|
||||
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6261@{#1106}
|
||||
Cr-Branched-From: 9755d9d81e4a8cb5b4f76b23b761457479dbb06b-refs/heads/main@{#1250580}
|
||||
|
||||
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc
|
||||
index 935dbb05a5021ffb80737e2f8e5497e887235946..6d920c33562de8d2bf11ae74101cf7ab1e929f5e 100644
|
||||
--- a/cc/paint/paint_op_reader.cc
|
||||
+++ b/cc/paint/paint_op_reader.cc
|
||||
@@ -1532,9 +1532,10 @@ inline void PaintOpReader::DidRead(size_t bytes_read) {
|
||||
// All data are aligned with PaintOpWriter::kDefaultAlignment at least.
|
||||
size_t aligned_bytes =
|
||||
base::bits::AlignUp(bytes_read, PaintOpWriter::kDefaultAlignment);
|
||||
- memory_ += aligned_bytes;
|
||||
DCHECK_LE(aligned_bytes, remaining_bytes_);
|
||||
- remaining_bytes_ -= aligned_bytes;
|
||||
+ bytes_read = std::min(aligned_bytes, remaining_bytes_);
|
||||
+ memory_ += bytes_read;
|
||||
+ remaining_bytes_ -= bytes_read;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
@@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Peter=20Bostr=C3=B6m?= <pbos@chromium.org>
|
||||
Date: Thu, 1 Feb 2024 21:24:43 +0000
|
||||
Subject: Fix racy iterator use in Node::AddConnection
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Before this fix an iterator to `connections_` which requires a lock
|
||||
would be dereferenced outside an unlock operation because the `it` taken
|
||||
from the map isn't understood as guarded by the same lock.
|
||||
|
||||
This takes a Ref<NodeLink> before unlocking which'll keep the link
|
||||
reference alive even if `connections_` is concurrently modified and the
|
||||
entry removed (or replaced).
|
||||
|
||||
(cherry picked from commit 1f2cbf5833d7f00d3fcbfd1f3ef0c1aff10c04cd)
|
||||
|
||||
Bug: 1523704
|
||||
Change-Id: I6f6fe4e34ec2c8268d4e7f33965a13e3b10f9f92
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5254025
|
||||
Commit-Queue: Peter Boström <pbos@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Auto-Submit: Peter Boström <pbos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1254709}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5260163
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1916}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/ipcz/src/ipcz/node.cc b/third_party/ipcz/src/ipcz/node.cc
|
||||
index a7162f9017d86d3ab3369d04add98527189dd33f..3a8eef652cc3381b608d89cfb6acd006d4ba378b 100644
|
||||
--- a/third_party/ipcz/src/ipcz/node.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/node.cc
|
||||
@@ -168,9 +168,10 @@ bool Node::AddConnection(const NodeName& remote_node_name,
|
||||
// handling an incoming NodeConnector message, we can err on the side of
|
||||
// caution (i.e. less re-entrancy in event handlers) by treating every
|
||||
// case like an API call.
|
||||
+ const Ref<NodeLink> link = it->second.link;
|
||||
mutex_.Unlock();
|
||||
const OperationContext context{OperationContext::kAPICall};
|
||||
- DropConnection(context, *it->second.link);
|
||||
+ DropConnection(context, *link);
|
||||
mutex_.Lock();
|
||||
}
|
||||
|
||||
87
patches/chromium/m120_ipcz_fix_a_few_weak_asserts.patch
Normal file
87
patches/chromium/m120_ipcz_fix_a_few_weak_asserts.patch
Normal file
@@ -0,0 +1,87 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Tue, 30 Jan 2024 21:36:01 +0000
|
||||
Subject: ipcz: Fix a few weak asserts
|
||||
|
||||
DriverMemory cloning should not weakly assert success, as it can fail in
|
||||
real production scenarios. Now Clone() will return an invalid
|
||||
DriverMemory object if it fails to duplicate the internal handle.
|
||||
Existing callers of Clone() are already durable to an invalid output, so
|
||||
this change results in graceful failures instead of undefined behavior.
|
||||
|
||||
This also replaces some weak asserts in DriverTransport creation with
|
||||
hardening asserts. We may want to fail more gracefully if these end
|
||||
up crashing a lot, but it seems unlikely.
|
||||
|
||||
(cherry picked from commit 4bd18c5a3a7a935716bbed197fba6d45a1122894)
|
||||
|
||||
Fixed: 1521571
|
||||
Change-Id: Id764b33ead8bbba58e61b3270920c839479eaa4a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5240312
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Alex Gough <ajgo@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1252882}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5250958
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/6099@{#1905}
|
||||
Cr-Branched-From: e6ee4500f7d6549a9ac1354f8d056da49ef406be-refs/heads/main@{#1217362}
|
||||
|
||||
diff --git a/third_party/ipcz/src/ipcz/driver_memory.cc b/third_party/ipcz/src/ipcz/driver_memory.cc
|
||||
index f8761985b78409fdb5420456661b0d227030cc8f..3bdc3aaf52d166a7691b5f28ebc86cc47600f7cc 100644
|
||||
--- a/third_party/ipcz/src/ipcz/driver_memory.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/driver_memory.cc
|
||||
@@ -30,10 +30,11 @@ DriverMemory::DriverMemory(const IpczDriver& driver, size_t num_bytes)
|
||||
: size_(num_bytes) {
|
||||
ABSL_ASSERT(num_bytes > 0);
|
||||
IpczDriverHandle handle;
|
||||
- IpczResult result =
|
||||
+ const IpczResult result =
|
||||
driver.AllocateSharedMemory(num_bytes, IPCZ_NO_FLAGS, nullptr, &handle);
|
||||
- ABSL_ASSERT(result == IPCZ_RESULT_OK);
|
||||
- memory_ = DriverObject(driver, handle);
|
||||
+ if (result == IPCZ_RESULT_OK) {
|
||||
+ memory_ = DriverObject(driver, handle);
|
||||
+ }
|
||||
}
|
||||
|
||||
DriverMemory::DriverMemory(DriverMemory&& other) = default;
|
||||
@@ -43,12 +44,14 @@ DriverMemory& DriverMemory::operator=(DriverMemory&& other) = default;
|
||||
DriverMemory::~DriverMemory() = default;
|
||||
|
||||
DriverMemory DriverMemory::Clone() {
|
||||
- ABSL_ASSERT(is_valid());
|
||||
+ ABSL_HARDENING_ASSERT(is_valid());
|
||||
|
||||
IpczDriverHandle handle;
|
||||
- IpczResult result = memory_.driver()->DuplicateSharedMemory(
|
||||
+ const IpczResult result = memory_.driver()->DuplicateSharedMemory(
|
||||
memory_.handle(), 0, nullptr, &handle);
|
||||
- ABSL_ASSERT(result == IPCZ_RESULT_OK);
|
||||
+ if (result != IPCZ_RESULT_OK) {
|
||||
+ return DriverMemory();
|
||||
+ }
|
||||
|
||||
return DriverMemory(DriverObject(*memory_.driver(), handle));
|
||||
}
|
||||
diff --git a/third_party/ipcz/src/ipcz/driver_transport.cc b/third_party/ipcz/src/ipcz/driver_transport.cc
|
||||
index 096f1b3bed3cfbe0074b074edba21bcfceacd897..dbeb69a0a881a82c9360118a017942ec6eb920f8 100644
|
||||
--- a/third_party/ipcz/src/ipcz/driver_transport.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/driver_transport.cc
|
||||
@@ -68,14 +68,14 @@ DriverTransport::Pair DriverTransport::CreatePair(
|
||||
IpczDriverHandle target_transport0 = IPCZ_INVALID_DRIVER_HANDLE;
|
||||
IpczDriverHandle target_transport1 = IPCZ_INVALID_DRIVER_HANDLE;
|
||||
if (transport0) {
|
||||
- ABSL_ASSERT(transport1);
|
||||
+ ABSL_HARDENING_ASSERT(transport1);
|
||||
target_transport0 = transport0->driver_object().handle();
|
||||
target_transport1 = transport1->driver_object().handle();
|
||||
}
|
||||
IpczResult result = driver.CreateTransports(
|
||||
target_transport0, target_transport1, IPCZ_NO_FLAGS, nullptr,
|
||||
&new_transport0, &new_transport1);
|
||||
- ABSL_ASSERT(result == IPCZ_RESULT_OK);
|
||||
+ ABSL_HARDENING_ASSERT(result == IPCZ_RESULT_OK);
|
||||
auto first =
|
||||
MakeRefCounted<DriverTransport>(DriverObject(driver, new_transport0));
|
||||
auto second =
|
||||
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joey Arhar <jarhar@chromium.org>
|
||||
Date: Wed, 21 Feb 2024 21:06:46 +0000
|
||||
Subject: M122: cherry pick CVE-2024-25062 libxml fix
|
||||
|
||||
This patch cherry picks the CVE-2024-25062 fix from libxml:
|
||||
https://gitlab.gnome.org/GNOME/libxml2/-/commit/1a66b176055d25ee635bf328c7b35b381db0b71d
|
||||
|
||||
Bug: 325094430
|
||||
Change-Id: I526ee718269ed8700b90885630b67f00f2f95089
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5310037
|
||||
Auto-Submit: Joey Arhar <jarhar@chromium.org>
|
||||
Commit-Queue: David Baron <dbaron@chromium.org>
|
||||
Reviewed-by: David Baron <dbaron@chromium.org>
|
||||
Commit-Queue: Joey Arhar <jarhar@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6261@{#913}
|
||||
Cr-Branched-From: 9755d9d81e4a8cb5b4f76b23b761457479dbb06b-refs/heads/main@{#1250580}
|
||||
|
||||
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
|
||||
index f3e311972eb41e768c905a451ef576706434eeec..17ffbdf2734a788ffbaab9df50fda68b56e91c53 100644
|
||||
--- a/third_party/libxml/README.chromium
|
||||
+++ b/third_party/libxml/README.chromium
|
||||
@@ -36,5 +36,6 @@ Modifications:
|
||||
- LIBXML_XINCLUDE_ENABLED
|
||||
- LIBXML_XPTR_ENABLED
|
||||
- LIBXML_ZLIB_ENABLED
|
||||
+- Cherry picked fix for CVE-2024-25062
|
||||
|
||||
This import was generated by the chromium/roll.py script.
|
||||
diff --git a/third_party/libxml/src/xmlreader.c b/third_party/libxml/src/xmlreader.c
|
||||
index 71f2f933cc3b5a1064637036aed09459f2d1ce89..82cc186ea829ea60582ea0f7056125bc3ff310f3 100644
|
||||
--- a/third_party/libxml/src/xmlreader.c
|
||||
+++ b/third_party/libxml/src/xmlreader.c
|
||||
@@ -1445,6 +1445,7 @@ node_found:
|
||||
* Handle XInclude if asked for
|
||||
*/
|
||||
if ((reader->xinclude) && (reader->in_xinclude == 0) &&
|
||||
+ (reader->state != XML_TEXTREADER_BACKTRACK) &&
|
||||
(reader->node != NULL) &&
|
||||
(reader->node->type == XML_ELEMENT_NODE) &&
|
||||
(reader->node->ns != NULL) &&
|
||||
@@ -0,0 +1,82 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Eugene Zemtsov <eugene@chromium.org>
|
||||
Date: Mon, 25 Mar 2024 19:28:44 +0000
|
||||
Subject: webcodecs: Disable async VideoFrame readback to mitigate a race
|
||||
|
||||
(cherry picked from commit fdc363eb7a1c1c194a02a4cb340534b1501b0f95)
|
||||
|
||||
Bug: 330575496
|
||||
Change-Id: I187a113528da9d1c4316186e3dd24f91dbfd818b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5386784
|
||||
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
|
||||
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1277172}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5391828
|
||||
Reviewed-by: Eugene Zemtsov <eugene@chromium.org>
|
||||
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
|
||||
Reviewed-by: Xiaohan Wang <xhwang@chromium.org>
|
||||
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6261@{#1124}
|
||||
Cr-Branched-From: 9755d9d81e4a8cb5b4f76b23b761457479dbb06b-refs/heads/main@{#1250580}
|
||||
|
||||
diff --git a/content/test/data/gpu/webcodecs/copyTo.html b/content/test/data/gpu/webcodecs/copyTo.html
|
||||
index 628b891ecc5eb675d426c83a5ad235839ed7d6c1..0931feefa628af2060cd927666879a3e72ba2959 100644
|
||||
--- a/content/test/data/gpu/webcodecs/copyTo.html
|
||||
+++ b/content/test/data/gpu/webcodecs/copyTo.html
|
||||
@@ -118,6 +118,16 @@ Take frames coming from various sources and read them using copyTo().
|
||||
let frame = await source.getNextFrame();
|
||||
let size = frame.allocationSize();
|
||||
|
||||
+ // Readback a whole frame to a regular buffer detach it
|
||||
+ {
|
||||
+ let buf = new ArrayBuffer(size);
|
||||
+ TEST.assert(readWholeBuffer(buf) == 0, "Buffer should be zero");
|
||||
+ let copy_promise = frame.copyTo(buf);
|
||||
+ buf.transfer(1);
|
||||
+ let layout = await copy_promise;
|
||||
+ TEST.assert(layout, "layout is empty / ArrayBuffer");
|
||||
+ }
|
||||
+
|
||||
// Readback a whole frame to a regular buffer and send it to a worker
|
||||
{
|
||||
let {worker, worker_promise } = makeWorker();
|
||||
@@ -158,4 +168,5 @@ Take frames coming from various sources and read them using copyTo().
|
||||
TEST.log('Test completed');
|
||||
}
|
||||
addManualTestButton([{'source_type': 'offscreen'}]);
|
||||
-</script>
|
||||
\ No newline at end of file
|
||||
+ addManualTestButton([{'source_type': 'arraybuffer'}]);
|
||||
+</script>
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
|
||||
index 365b18025d5a88af4910bdc4e544210c355c4105..eb7a2c50118f6515b2984c7f0a9fadabd9a5f16e 100644
|
||||
--- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
|
||||
@@ -79,6 +79,11 @@ namespace blink {
|
||||
|
||||
namespace {
|
||||
|
||||
+// Controls if VideoFrame.copyTo() reads GPU frames asynchronously
|
||||
+BASE_FEATURE(kVideoFrameAsyncCopyTo,
|
||||
+ "VideoFrameAsyncCopyTo",
|
||||
+ base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
+
|
||||
media::VideoPixelFormat ToMediaPixelFormat(V8VideoPixelFormat::Enum fmt) {
|
||||
switch (fmt) {
|
||||
case V8VideoPixelFormat::Enum::kI420:
|
||||
@@ -1131,9 +1136,11 @@ ScriptPromise VideoFrame::copyTo(ScriptState* script_state,
|
||||
} else {
|
||||
DCHECK(local_frame->HasTextures());
|
||||
|
||||
- if (auto* resolver = CopyToAsync(script_state, local_frame, src_rect,
|
||||
- destination, dest_layout)) {
|
||||
- return resolver->Promise();
|
||||
+ if (base::FeatureList::IsEnabled(kVideoFrameAsyncCopyTo)) {
|
||||
+ if (auto* resolver = CopyToAsync(script_state, local_frame, src_rect,
|
||||
+ destination, dest_layout)) {
|
||||
+ return resolver->Promise();
|
||||
+ }
|
||||
}
|
||||
|
||||
if (!CopyTexturablePlanes(*local_frame, src_rect, dest_layout, buffer)) {
|
||||
156
patches/chromium/prevent_mojotrap_event_re-ordering.patch
Normal file
156
patches/chromium/prevent_mojotrap_event_re-ordering.patch
Normal file
@@ -0,0 +1,156 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Thu, 15 Feb 2024 20:30:22 +0000
|
||||
Subject: Prevent MojoTrap event re-ordering
|
||||
|
||||
(cherry picked from commit 3557a2fcbdd8167f97ca81171be2e0da9c4f0647)
|
||||
|
||||
Fixed: 1508753
|
||||
Change-Id: I9ec14a12e7d1d147bda63703e1d6619fa30c8a51
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5253039
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Robert Sesek <rsesek@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1254840}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5299857
|
||||
Reviewed-by: Oksana Zhuravlova <oksamyt@chromium.org>
|
||||
Commit-Queue: Alex Gough <ajgo@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6261@{#794}
|
||||
Cr-Branched-From: 9755d9d81e4a8cb5b4f76b23b761457479dbb06b-refs/heads/main@{#1250580}
|
||||
|
||||
diff --git a/mojo/core/ipcz_driver/mojo_trap.cc b/mojo/core/ipcz_driver/mojo_trap.cc
|
||||
index 7a5765a74a7f64e584b0a080e659c88c019adcbb..2c98335dd7846fe44fd048265078dfffcb0b63f6 100644
|
||||
--- a/mojo/core/ipcz_driver/mojo_trap.cc
|
||||
+++ b/mojo/core/ipcz_driver/mojo_trap.cc
|
||||
@@ -544,7 +544,15 @@ void MojoTrap::DispatchOrQueueEvent(Trigger& trigger,
|
||||
}
|
||||
|
||||
dispatching_thread_ = base::PlatformThread::CurrentRef();
|
||||
- DispatchEvent(event);
|
||||
+
|
||||
+ // If `trigger.removed` is true, then either this is the cancellation event
|
||||
+ // for the trigger (in which case it's OK to dispatch), or it was cancelled on
|
||||
+ // some other thread while we were blocked above. In the latter case, this
|
||||
+ // event is no longer valid and cannot be dispatched.
|
||||
+ // See https://crbug.com/1508753.
|
||||
+ if (!trigger.removed || event.result == MOJO_RESULT_CANCELLED) {
|
||||
+ DispatchEvent(event);
|
||||
+ }
|
||||
|
||||
// NOTE: This vector is only shrunk by the clear() below, but it may
|
||||
// accumulate more events during each iteration. Hence we iterate by index.
|
||||
diff --git a/mojo/core/trap_unittest.cc b/mojo/core/trap_unittest.cc
|
||||
index 0fd449d9598810fd34372d69d1d1599a0c88b955..4058da72eef8b5a11432b9a17d6ff3ecfd1306e8 100644
|
||||
--- a/mojo/core/trap_unittest.cc
|
||||
+++ b/mojo/core/trap_unittest.cc
|
||||
@@ -1747,6 +1747,111 @@ TEST_F(TrapTest, TriggerDuringDestruction) {
|
||||
MojoClose(b);
|
||||
}
|
||||
|
||||
+TEST_F(TrapTest, RaceDispatchAndBlockedCancel) {
|
||||
+ // Regression test for https://crbug.com/1508753. This bug was caused by
|
||||
+ // reordering of a MOJO_RESULT_CANCELLED event to before some other event for
|
||||
+ // the same trap context, violating an API constraint that must be upheld for
|
||||
+ // memory safety in application code. The scenario which could elicit the bug
|
||||
+ // was as follows:
|
||||
+ //
|
||||
+ // 1. A single trap is watching two pipes, P and Q.
|
||||
+ // 2. Thread A closes pipe P, triggering a CANCELLED event.
|
||||
+ // 3. Thread A re-arms the trap from within the CANCELLED event handler.
|
||||
+ // 4. Thread B changes Q's state to elicit a event for Q (not CANCELLED).
|
||||
+ // 5. Thread B dispatch is blocked because thread A is still dispatching.
|
||||
+ // 6. Before thread B gets a chance to be scheduled, thread A closes Q.
|
||||
+ // 7. Thread A dispatches a CANCELLED event for Q.
|
||||
+ // 8. Thread B is scheduled and proceeds to dispatch its Q event. [BAD]
|
||||
+
|
||||
+ struct State;
|
||||
+
|
||||
+ struct Pipe {
|
||||
+ explicit Pipe(State* state) : state(state) { CreateMessagePipe(&a, &b); }
|
||||
+
|
||||
+ uintptr_t context() const { return reinterpret_cast<uintptr_t>(this); }
|
||||
+
|
||||
+ MojoHandle a;
|
||||
+ MojoHandle b;
|
||||
+ bool trigger_cancelled = false;
|
||||
+
|
||||
+ // Back-reference to common state so it's reachable from the event handler.
|
||||
+ const raw_ptr<State> state;
|
||||
+ };
|
||||
+
|
||||
+ struct State {
|
||||
+ Pipe pipe0{this};
|
||||
+ Pipe pipe1{this};
|
||||
+ MojoHandle trap;
|
||||
+ base::WaitableEvent event;
|
||||
+ };
|
||||
+ State state;
|
||||
+
|
||||
+ // NOTE: + to turn the lambda into a function pointer.
|
||||
+ const MojoTrapEventHandler event_handler = +[](const MojoTrapEvent* event) {
|
||||
+ auto& pipe = *reinterpret_cast<Pipe*>(event->trigger_context);
|
||||
+ auto& state = *pipe.state;
|
||||
+
|
||||
+ // If the bug is present, this expectation can fail flakily. No event should
|
||||
+ // fire for a pipe after its watch has been cancelled.
|
||||
+ EXPECT_FALSE(pipe.trigger_cancelled);
|
||||
+
|
||||
+ if (event->result == MOJO_RESULT_CANCELLED) {
|
||||
+ pipe.trigger_cancelled = true;
|
||||
+
|
||||
+ if (&pipe == &state.pipe0) {
|
||||
+ // When pipe0's watch is cancelled (on the main thread by closure down
|
||||
+ // below) we re-arm the trap immediately. This must succeed because
|
||||
+ // `pipe1.a` is now the only handle being watched, and it's still in an
|
||||
+ // uninteresting state.
|
||||
+ EXPECT_EQ(MOJO_RESULT_OK,
|
||||
+ MojoArmTrap(state.trap, nullptr, nullptr, nullptr));
|
||||
+
|
||||
+ // Unblock the other thread so it can elicit a trap event on pipe1 now
|
||||
+ // that the trap is re-armed. It will still block just before
|
||||
+ // dispatching as long as we're still in this event handler on the main
|
||||
+ // thread.
|
||||
+ state.event.Signal();
|
||||
+
|
||||
+ // A nice long delay to make it very likely for the waiting
|
||||
+ // ThreadedRunner to progress right up to its event dispatch.
|
||||
+ base::PlatformThread::Sleep(base::Milliseconds(10));
|
||||
+
|
||||
+ // Trigger cancellation for pipe1 by closing its `a`. This will queue a
|
||||
+ // CANCELLED event to fire on the same thread immediately after we
|
||||
+ // return from this handler.
|
||||
+ MojoClose(state.pipe1.a);
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ EXPECT_EQ(MOJO_RESULT_OK,
|
||||
+ MojoCreateTrap(event_handler, nullptr, &state.trap));
|
||||
+ EXPECT_EQ(
|
||||
+ MOJO_RESULT_OK,
|
||||
+ MojoAddTrigger(state.trap, state.pipe0.a, MOJO_HANDLE_SIGNAL_READABLE,
|
||||
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
|
||||
+ state.pipe0.context(), nullptr));
|
||||
+ EXPECT_EQ(
|
||||
+ MOJO_RESULT_OK,
|
||||
+ MojoAddTrigger(state.trap, state.pipe1.a, MOJO_HANDLE_SIGNAL_READABLE,
|
||||
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
|
||||
+ state.pipe1.context(), nullptr));
|
||||
+ EXPECT_EQ(MOJO_RESULT_OK, MojoArmTrap(state.trap, nullptr, nullptr, nullptr));
|
||||
+
|
||||
+ ThreadedRunner close_pipe1_b(base::BindLambdaForTesting([&] {
|
||||
+ state.event.Wait();
|
||||
+ MojoClose(state.pipe1.b);
|
||||
+ }));
|
||||
+ close_pipe1_b.Start();
|
||||
+
|
||||
+ // Trigger cancellation of the watch on `pipe0.a`. See event_handler above.
|
||||
+ MojoClose(state.pipe0.a);
|
||||
+
|
||||
+ close_pipe1_b.Join();
|
||||
+ MojoClose(state.pipe0.b);
|
||||
+ MojoClose(state.trap);
|
||||
+}
|
||||
+
|
||||
base::RepeatingClosure g_do_random_thing_callback;
|
||||
|
||||
void ReadAllMessages(const MojoTrapEvent* event) {
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joshua Peraza <jperaza@chromium.org>
|
||||
Date: Tue, 5 Mar 2024 18:09:48 +0000
|
||||
Subject: Update Crashpad to 37afd37401253ebcebcf6e07ce15c8cfecb1a1cc
|
||||
|
||||
29ac83caeb94 [Fuchsia] remove use of fuchsia mac sdk
|
||||
37afd3740125 Properly update iterator
|
||||
|
||||
(cherry picked from commit 80b0e498bec1722e8cc310fe52698e7b690956f2)
|
||||
|
||||
Bug: 325296797
|
||||
Change-Id: I7eb39d1bccec802f1b043eebd20ec0e658fe0e04
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5311633
|
||||
Reviewed-by: Nico Weber <thakis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1264232}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5335538
|
||||
Reviewed-by: Mark Mentovai <mark@chromium.org>
|
||||
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6261@{#1024}
|
||||
Cr-Branched-From: 9755d9d81e4a8cb5b4f76b23b761457479dbb06b-refs/heads/main@{#1250580}
|
||||
|
||||
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
|
||||
index 9edcee3aa81a84cd38bba2660557dfc6f48e380c..bafe29b422506207a11a22f6793c38d6c5fa5a5f 100644
|
||||
--- a/third_party/crashpad/README.chromium
|
||||
+++ b/third_party/crashpad/README.chromium
|
||||
@@ -1,8 +1,8 @@
|
||||
Name: Crashpad
|
||||
Short Name: crashpad
|
||||
URL: https://crashpad.chromium.org/
|
||||
-Version: unknown
|
||||
-Revision: a7cfe95351e301512eb0efc03f92fee63c1c82b2
|
||||
+Version: N/A
|
||||
+Revision: 37afd37401253ebcebcf6e07ce15c8cfecb1a1cc
|
||||
License: Apache 2.0
|
||||
License File: crashpad/LICENSE
|
||||
Security Critical: yes
|
||||
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS
|
||||
index b7d44b11c3f8eb8275971eb29c5bcca313f70179..f6f7a31963245b47724eb75584033e68c90a90d6 100644
|
||||
--- a/third_party/crashpad/crashpad/DEPS
|
||||
+++ b/third_party/crashpad/crashpad/DEPS
|
||||
@@ -121,16 +121,6 @@ deps = {
|
||||
'0d6902558d92fe3d49ba9a8f638ddea829be595b',
|
||||
'condition': 'checkout_fuchsia',
|
||||
},
|
||||
- 'crashpad/third_party/fuchsia/sdk/mac-amd64': {
|
||||
- 'packages': [
|
||||
- {
|
||||
- 'package': 'fuchsia/sdk/core/mac-amd64',
|
||||
- 'version': 'latest'
|
||||
- },
|
||||
- ],
|
||||
- 'condition': 'checkout_fuchsia and host_os == "mac"',
|
||||
- 'dep_type': 'cipd'
|
||||
- },
|
||||
'crashpad/third_party/fuchsia/sdk/linux-amd64': {
|
||||
'packages': [
|
||||
{
|
||||
diff --git a/third_party/crashpad/crashpad/snapshot/sanitized/module_snapshot_sanitized.cc b/third_party/crashpad/crashpad/snapshot/sanitized/module_snapshot_sanitized.cc
|
||||
index 192b4cb10add6e3aaa70b96b86bc8ae90b90a070..476ebe019eee87d76a8bceaa885dc58f01c6af62 100644
|
||||
--- a/third_party/crashpad/crashpad/snapshot/sanitized/module_snapshot_sanitized.cc
|
||||
+++ b/third_party/crashpad/crashpad/snapshot/sanitized/module_snapshot_sanitized.cc
|
||||
@@ -97,9 +97,11 @@ ModuleSnapshotSanitized::AnnotationsSimpleMap() const {
|
||||
std::map<std::string, std::string> annotations =
|
||||
snapshot_->AnnotationsSimpleMap();
|
||||
if (allowed_annotations_) {
|
||||
- for (auto kv = annotations.begin(); kv != annotations.end(); ++kv) {
|
||||
- if (!KeyIsAllowed(kv->first, *allowed_annotations_)) {
|
||||
- annotations.erase(kv);
|
||||
+ for (auto kv = annotations.begin(); kv != annotations.end();) {
|
||||
+ if (KeyIsAllowed(kv->first, *allowed_annotations_)) {
|
||||
+ ++kv;
|
||||
+ } else {
|
||||
+ kv = annotations.erase(kv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,19 @@
|
||||
{
|
||||
"src/electron/patches/chromium": "src",
|
||||
|
||||
"src/electron/patches/boringssl": "src/third_party/boringssl/src",
|
||||
|
||||
"src/electron/patches/devtools_frontend": "src/third_party/devtools-frontend/src",
|
||||
|
||||
"src/electron/patches/ffmpeg": "src/third_party/ffmpeg",
|
||||
|
||||
"src/electron/patches/v8": "src/v8",
|
||||
|
||||
"src/electron/patches/node": "src/third_party/electron_node",
|
||||
|
||||
"src/electron/patches/nan": "src/third_party/nan",
|
||||
|
||||
"src/electron/patches/perfetto": "src/third_party/perfetto",
|
||||
|
||||
"src/electron/patches/squirrel.mac": "src/third_party/squirrel.mac",
|
||||
|
||||
"src/electron/patches/Mantle": "src/third_party/squirrel.mac/vendor/Mantle",
|
||||
|
||||
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC",
|
||||
|
||||
"src/electron/patches/webrtc": "src/third_party/webrtc",
|
||||
|
||||
"src/electron/patches/libavif": "src/third_party/libavif/src",
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/sqlite": "src/third_party/sqlite/src"
|
||||
}
|
||||
[
|
||||
{ "patch_dir": "src/electron/patches/chromium", "repo": "src" },
|
||||
{ "patch_dir": "src/electron/patches/boringssl", "repo": "src/third_party/boringssl/src" },
|
||||
{ "patch_dir": "src/electron/patches/devtools_frontend", "repo": "src/third_party/devtools-frontend/src" },
|
||||
{ "patch_dir": "src/electron/patches/ffmpeg", "repo": "src/third_party/ffmpeg" },
|
||||
{ "patch_dir": "src/electron/patches/v8", "repo": "src/v8" },
|
||||
{ "patch_dir": "src/electron/patches/node", "repo": "src/third_party/electron_node" },
|
||||
{ "patch_dir": "src/electron/patches/nan", "repo": "src/third_party/nan" },
|
||||
{ "patch_dir": "src/electron/patches/perfetto", "repo": "src/third_party/perfetto" },
|
||||
{ "patch_dir": "src/electron/patches/squirrel.mac", "repo": "src/third_party/squirrel.mac" },
|
||||
{ "patch_dir": "src/electron/patches/Mantle", "repo": "src/third_party/squirrel.mac/vendor/Mantle" },
|
||||
{ "patch_dir": "src/electron/patches/ReactiveObjC", "repo": "src/third_party/squirrel.mac/vendor/ReactiveObjC" },
|
||||
{ "patch_dir": "src/electron/patches/webrtc", "repo": "src/third_party/webrtc" },
|
||||
{ "patch_dir": "src/electron/patches/libavif", "repo": "src/third_party/libavif/src" },
|
||||
{ "patch_dir": "src/electron/patches/angle", "repo": "src/third_party/angle" },
|
||||
{ "patch_dir": "src/electron/patches/sqlite", "repo": "src/third_party/sqlite/src" },
|
||||
{ "patch_dir": "src/electron/patches/libvpx", "repo": "src/third_party/libvpx/source/libvpx" },
|
||||
{ "patch_dir": "src/electron/patches/DirectXShaderCompiler", "repo": "src/third_party/dawn/third_party/dxc" }
|
||||
]
|
||||
|
||||
1
patches/dxc/.patches
Normal file
1
patches/dxc/.patches
Normal file
@@ -0,0 +1 @@
|
||||
fix_hlmatrixlowerpass_leaving_call_to_dangling_functionval.patch
|
||||
@@ -0,0 +1,2 @@
|
||||
fix_to_buffer_alloc_for_vp9_bitstream_worker_data.patch
|
||||
vp9_fix_to_integer_overflow_test.patch
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marco Paniconi <marpan@google.com>
|
||||
Date: Wed, 13 Mar 2024 10:58:17 -0700
|
||||
Subject: Fix to buffer alloc for vp9_bitstream_worker_data
|
||||
|
||||
The code was using the bitstream_worker_data when it
|
||||
wasn't allocated for big enough size. This is because
|
||||
the existing condition was to only re-alloc the
|
||||
bitstream_worker_data when current dest_size was larger
|
||||
than the current frame_size. But under resolution change
|
||||
where frame_size is increased, beyond the current dest_size,
|
||||
we need to allow re-alloc to the new size.
|
||||
|
||||
The existing condition to re-alloc when dest_size is
|
||||
larger than frame_size (which is not required) is kept
|
||||
for now.
|
||||
|
||||
Also increase the dest_size to account for image format.
|
||||
|
||||
Added tests, for both ROW_MT=0 and 1, that reproduce
|
||||
the failures in the bugs below.
|
||||
|
||||
Note: this issue only affects the REALTIME encoding path.
|
||||
|
||||
Bug: b/329088759, b/329674887, b/329179808
|
||||
|
||||
Change-Id: Icd65dbc5317120304d803f648d4bd9405710db6f
|
||||
(cherry picked from commit c29e63728316486082dd6083c2062434b441b77d)
|
||||
|
||||
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
|
||||
index ca56d14aa1e31e4791f8772316e449b771aae4fc..88a031e5fc1cf7b6cf0a441664dbbc62006c1790 100644
|
||||
--- a/vp9/encoder/vp9_bitstream.c
|
||||
+++ b/vp9/encoder/vp9_bitstream.c
|
||||
@@ -962,6 +962,14 @@ void vp9_bitstream_encode_tiles_buffer_dealloc(VP9_COMP *const cpi) {
|
||||
}
|
||||
}
|
||||
|
||||
+static int encode_tiles_buffer_alloc_size(VP9_COMP *const cpi) {
|
||||
+ VP9_COMMON *const cm = &cpi->common;
|
||||
+ const int image_bps =
|
||||
+ (8 + 2 * (8 >> (cm->subsampling_x + cm->subsampling_y))) *
|
||||
+ (1 + (cm->bit_depth > 8));
|
||||
+ return cpi->oxcf.width * cpi->oxcf.height * image_bps / 8;
|
||||
+}
|
||||
+
|
||||
static void encode_tiles_buffer_alloc(VP9_COMP *const cpi) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
int i;
|
||||
@@ -972,7 +980,7 @@ static void encode_tiles_buffer_alloc(VP9_COMP *const cpi) {
|
||||
memset(cpi->vp9_bitstream_worker_data, 0, worker_data_size);
|
||||
for (i = 1; i < cpi->num_workers; ++i) {
|
||||
cpi->vp9_bitstream_worker_data[i].dest_size =
|
||||
- cpi->oxcf.width * cpi->oxcf.height;
|
||||
+ encode_tiles_buffer_alloc_size(cpi);
|
||||
CHECK_MEM_ERROR(&cm->error, cpi->vp9_bitstream_worker_data[i].dest,
|
||||
vpx_malloc(cpi->vp9_bitstream_worker_data[i].dest_size));
|
||||
}
|
||||
@@ -987,8 +995,8 @@ static size_t encode_tiles_mt(VP9_COMP *cpi, uint8_t *data_ptr) {
|
||||
int tile_col = 0;
|
||||
|
||||
if (!cpi->vp9_bitstream_worker_data ||
|
||||
- cpi->vp9_bitstream_worker_data[1].dest_size >
|
||||
- (cpi->oxcf.width * cpi->oxcf.height)) {
|
||||
+ cpi->vp9_bitstream_worker_data[1].dest_size !=
|
||||
+ encode_tiles_buffer_alloc_size(cpi)) {
|
||||
vp9_bitstream_encode_tiles_buffer_dealloc(cpi);
|
||||
encode_tiles_buffer_alloc(cpi);
|
||||
}
|
||||
28
patches/libvpx/vp9_fix_to_integer_overflow_test.patch
Normal file
28
patches/libvpx/vp9_fix_to_integer_overflow_test.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marco Paniconi <marpan@google.com>
|
||||
Date: Sat, 16 Mar 2024 10:39:28 -0700
|
||||
Subject: vp9: fix to integer overflow test
|
||||
|
||||
failure for the 16k test: issue introduced
|
||||
in: c29e637283
|
||||
|
||||
Bug: b/329088759, b/329674887, b/329179808
|
||||
|
||||
Change-Id: I88e8a36b7f13223997c3006c84aec9cfa48c0bcf
|
||||
(cherry picked from commit 19832b1702d5b0adf616a0e080abd5207c8445b5)
|
||||
|
||||
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
|
||||
index 88a031e5fc1cf7b6cf0a441664dbbc62006c1790..d3c029da4bacafdb19aa6bfb9865ccbf2db33393 100644
|
||||
--- a/vp9/encoder/vp9_bitstream.c
|
||||
+++ b/vp9/encoder/vp9_bitstream.c
|
||||
@@ -967,7 +967,9 @@ static int encode_tiles_buffer_alloc_size(VP9_COMP *const cpi) {
|
||||
const int image_bps =
|
||||
(8 + 2 * (8 >> (cm->subsampling_x + cm->subsampling_y))) *
|
||||
(1 + (cm->bit_depth > 8));
|
||||
- return cpi->oxcf.width * cpi->oxcf.height * image_bps / 8;
|
||||
+ const int64_t size =
|
||||
+ (int64_t)cpi->oxcf.width * cpi->oxcf.height * image_bps / 8;
|
||||
+ return (int)size;
|
||||
}
|
||||
|
||||
static void encode_tiles_buffer_alloc(VP9_COMP *const cpi) {
|
||||
@@ -1,23 +1,9 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Mon, 22 Jan 2024 13:45:55 +0900
|
||||
Date: Mon, 4 Mar 2024 11:41:18 +0900
|
||||
Subject: src: preload function for Environment
|
||||
|
||||
https://github.com/nodejs/node/pull/51539
|
||||
|
||||
This PR adds a |preload| arg to the node::CreateEnvironment to allow
|
||||
embedders to set a preload function for the environment, which will run
|
||||
after the environment is loaded and before the main script runs.
|
||||
|
||||
This is similiar to the --require CLI option, but runs a C++ function,
|
||||
and can only be set by embedders.
|
||||
|
||||
The preload function can be used by embedders to inject scripts before
|
||||
running the main script, for example:
|
||||
1. In Electron it is used to initialize the ASAR virtual filesystem,
|
||||
inject custom process properties, etc.
|
||||
2. In VS Code it can be used to reset the module search paths for
|
||||
extensions.
|
||||
Backport https://github.com/nodejs/node/pull/51539
|
||||
|
||||
diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js
|
||||
index 31f5d1528c840a2926b59b2b1c82ff265588a37a..1e37bd59f53d3a194b2492c83f8e7299c42c828c 100644
|
||||
@@ -45,120 +31,80 @@ index 31f5d1528c840a2926b59b2b1c82ff265588a37a..1e37bd59f53d3a194b2492c83f8e7299
|
||||
// For user code, we preload modules if `-r` is passed
|
||||
const preloadModules = getOptionValue('--require');
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index c4caef25af670658965fc740ce03c2d2c4ed3e66..19443a9672441da5b98921eab9385083a72e3b7e 100644
|
||||
index c4caef25af670658965fc740ce03c2d2c4ed3e66..465ff36b79c36d29777c7b1abe3a35d3be5de93e 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -404,14 +404,16 @@ Environment* CreateEnvironment(
|
||||
const std::vector<std::string>& exec_args,
|
||||
EnvironmentFlags::Flags flags,
|
||||
ThreadId thread_id,
|
||||
- std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
|
||||
+ std::unique_ptr<InspectorParentHandle> inspector_parent_handle,
|
||||
+ EmbedderPreloadCallback preload) {
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
HandleScope handle_scope(isolate);
|
||||
Context::Scope context_scope(context);
|
||||
// TODO(addaleax): This is a much better place for parsing per-Environment
|
||||
// options than the global parse call.
|
||||
Environment* env = new Environment(
|
||||
- isolate_data, context, args, exec_args, nullptr, flags, thread_id);
|
||||
+ isolate_data, context, args, exec_args, nullptr, flags, thread_id,
|
||||
+ std::move(preload));
|
||||
@@ -484,18 +484,22 @@ NODE_EXTERN std::unique_ptr<InspectorParentHandle> GetInspectorParentHandle(
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_INSPECTOR
|
||||
if (env->should_create_inspector()) {
|
||||
-MaybeLocal<Value> LoadEnvironment(
|
||||
- Environment* env,
|
||||
- StartExecutionCallback cb) {
|
||||
+MaybeLocal<Value> LoadEnvironment(Environment* env,
|
||||
+ StartExecutionCallback cb,
|
||||
+ EmbedderPreloadCallback preload) {
|
||||
env->InitializeLibuv();
|
||||
env->InitializeDiagnostics();
|
||||
+ if (preload) {
|
||||
+ env->set_embedder_preload(std::move(preload));
|
||||
+ }
|
||||
|
||||
return StartExecution(env, cb);
|
||||
}
|
||||
|
||||
MaybeLocal<Value> LoadEnvironment(
|
||||
Environment* env,
|
||||
- const char* main_script_source_utf8) {
|
||||
+ const char* main_script_source_utf8,
|
||||
+ EmbedderPreloadCallback preload) {
|
||||
CHECK_NOT_NULL(main_script_source_utf8);
|
||||
return LoadEnvironment(
|
||||
env, [&](const StartExecutionCallbackInfo& info) -> MaybeLocal<Value> {
|
||||
@@ -508,7 +512,8 @@ MaybeLocal<Value> LoadEnvironment(
|
||||
std::vector<Local<Value>> args = {realm->process_object(),
|
||||
realm->builtin_module_require()};
|
||||
return realm->ExecuteBootstrapper(name.c_str(), &args);
|
||||
- });
|
||||
+ },
|
||||
+ std::move(preload));
|
||||
}
|
||||
|
||||
Environment* GetCurrentEnvironment(Local<Context> context) {
|
||||
diff --git a/src/env-inl.h b/src/env-inl.h
|
||||
index debd982c75805c51ea7d01229b9d635550060503..6af9217acb6f22c89bc92708aa9ab3d021c5e5bf 100644
|
||||
index debd982c75805c51ea7d01229b9d635550060503..a6f160b6e28a01a31d6bb06fcfa384c748463c50 100644
|
||||
--- a/src/env-inl.h
|
||||
+++ b/src/env-inl.h
|
||||
@@ -388,6 +388,10 @@ inline std::vector<double>* Environment::destroy_async_id_list() {
|
||||
@@ -388,6 +388,14 @@ inline std::vector<double>* Environment::destroy_async_id_list() {
|
||||
return &destroy_async_id_list_;
|
||||
}
|
||||
|
||||
+inline const EmbedderPreloadCallback& Environment::embedder_preload() const {
|
||||
+ return embedder_preload_;
|
||||
+}
|
||||
+
|
||||
+inline void Environment::set_embedder_preload(EmbedderPreloadCallback fn) {
|
||||
+ embedder_preload_ = std::move(fn);
|
||||
+}
|
||||
+
|
||||
inline double Environment::new_async_id() {
|
||||
async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1;
|
||||
return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter];
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index 6e8b314680c9175d8d513cc72382012ae5e70b26..e416bca327f181884ff8dad2b3a82ad826c0f3b5 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -645,7 +645,8 @@ Environment::Environment(IsolateData* isolate_data,
|
||||
const std::vector<std::string>& exec_args,
|
||||
const EnvSerializeInfo* env_info,
|
||||
EnvironmentFlags::Flags flags,
|
||||
- ThreadId thread_id)
|
||||
+ ThreadId thread_id,
|
||||
+ EmbedderPreloadCallback preload)
|
||||
: isolate_(isolate),
|
||||
isolate_data_(isolate_data),
|
||||
async_hooks_(isolate, MAYBE_FIELD_PTR(env_info, async_hooks)),
|
||||
@@ -668,7 +669,8 @@ Environment::Environment(IsolateData* isolate_data,
|
||||
flags_(flags),
|
||||
thread_id_(thread_id.id == static_cast<uint64_t>(-1)
|
||||
? AllocateEnvironmentThreadId().id
|
||||
- : thread_id.id) {
|
||||
+ : thread_id.id),
|
||||
+ embedder_preload_(std::move(preload)) {
|
||||
// We'll be creating new objects so make sure we've entered the context.
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
@@ -738,14 +740,16 @@ Environment::Environment(IsolateData* isolate_data,
|
||||
const std::vector<std::string>& exec_args,
|
||||
const EnvSerializeInfo* env_info,
|
||||
EnvironmentFlags::Flags flags,
|
||||
- ThreadId thread_id)
|
||||
+ ThreadId thread_id,
|
||||
+ EmbedderPreloadCallback preload)
|
||||
: Environment(isolate_data,
|
||||
context->GetIsolate(),
|
||||
args,
|
||||
exec_args,
|
||||
env_info,
|
||||
flags,
|
||||
- thread_id) {
|
||||
+ thread_id,
|
||||
+ std::move(preload)) {
|
||||
InitializeMainContext(context, env_info);
|
||||
}
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index c914b621f50bcd6bce2617fef9e48737235aa516..d2e7f8534498ca171986cf77ef19d2fc9b950a5b 100644
|
||||
index c914b621f50bcd6bce2617fef9e48737235aa516..e8ea98f193fcf579c20c3126dd441850c608752e 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -579,7 +579,8 @@ class Environment : public MemoryRetainer {
|
||||
const std::vector<std::string>& exec_args,
|
||||
const EnvSerializeInfo* env_info,
|
||||
EnvironmentFlags::Flags flags,
|
||||
- ThreadId thread_id);
|
||||
+ ThreadId thread_id,
|
||||
+ EmbedderPreloadCallback preload);
|
||||
void InitializeMainContext(v8::Local<v8::Context> context,
|
||||
const EnvSerializeInfo* env_info);
|
||||
// Create an Environment and initialize the provided principal context for it.
|
||||
@@ -589,7 +590,8 @@ class Environment : public MemoryRetainer {
|
||||
const std::vector<std::string>& exec_args,
|
||||
const EnvSerializeInfo* env_info,
|
||||
EnvironmentFlags::Flags flags,
|
||||
- ThreadId thread_id);
|
||||
+ ThreadId thread_id,
|
||||
+ EmbedderPreloadCallback preload);
|
||||
~Environment() override;
|
||||
|
||||
void InitializeLibuv();
|
||||
@@ -933,6 +935,8 @@ class Environment : public MemoryRetainer {
|
||||
@@ -933,6 +933,9 @@ class Environment : public MemoryRetainer {
|
||||
|
||||
#endif // HAVE_INSPECTOR
|
||||
|
||||
+ inline const EmbedderPreloadCallback& embedder_preload() const;
|
||||
+ inline void set_embedder_preload(EmbedderPreloadCallback fn);
|
||||
+
|
||||
inline void set_process_exit_handler(
|
||||
std::function<void(Environment*, int)>&& handler);
|
||||
|
||||
@@ -1101,6 +1105,7 @@ class Environment : public MemoryRetainer {
|
||||
@@ -1101,6 +1104,7 @@ class Environment : public MemoryRetainer {
|
||||
DefaultProcessExitHandler };
|
||||
|
||||
std::unique_ptr<Realm> principal_realm_ = nullptr;
|
||||
@@ -167,55 +113,45 @@ index c914b621f50bcd6bce2617fef9e48737235aa516..d2e7f8534498ca171986cf77ef19d2fc
|
||||
// Used by allocate_managed_buffer() and release_managed_buffer() to keep
|
||||
// track of the BackingStore for a given pointer.
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 26368061a909e6abc62a4cf261a5dbbd79404f1a..bb4065e33164c3ea762a27b71606ab4ed7b1b336 100644
|
||||
index 26368061a909e6abc62a4cf261a5dbbd79404f1a..0dec1e311d7c00c2b830a0b2a6bde4336aebe68b 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -593,9 +593,21 @@ struct InspectorParentHandle {
|
||||
virtual ~InspectorParentHandle();
|
||||
};
|
||||
@@ -630,13 +630,33 @@ struct StartExecutionCallbackInfo {
|
||||
|
||||
using StartExecutionCallback =
|
||||
std::function<v8::MaybeLocal<v8::Value>(const StartExecutionCallbackInfo&)>;
|
||||
+using EmbedderPreloadCallback =
|
||||
+ std::function<void(Environment* env,
|
||||
+ v8::Local<v8::Value> process,
|
||||
+ v8::Local<v8::Value> require)>;
|
||||
+
|
||||
// TODO(addaleax): Maybe move per-Environment options parsing here.
|
||||
// Returns nullptr when the Environment cannot be created e.g. there are
|
||||
// pending JavaScript exceptions.
|
||||
+//
|
||||
+// The |preload| function will run before executing the entry point, which
|
||||
+// is usually used by embedders to inject scripts. The function is executed
|
||||
+// with preload(process, require), and the passed require function has access
|
||||
+// to internal Node.js modules. The |preload| function is inherited by worker
|
||||
+// threads and thus will run in work threads, so make sure the function is
|
||||
+// thread-safe.
|
||||
NODE_EXTERN Environment* CreateEnvironment(
|
||||
IsolateData* isolate_data,
|
||||
v8::Local<v8::Context> context,
|
||||
@@ -603,7 +615,8 @@ NODE_EXTERN Environment* CreateEnvironment(
|
||||
const std::vector<std::string>& exec_args,
|
||||
EnvironmentFlags::Flags flags = EnvironmentFlags::kDefaultFlags,
|
||||
ThreadId thread_id = {} /* allocates a thread id automatically */,
|
||||
- std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {});
|
||||
+ std::unique_ptr<InspectorParentHandle> inspector_parent_handle = {},
|
||||
+ EmbedderPreloadCallback preload = nullptr);
|
||||
|
||||
// Returns a handle that can be passed to `LoadEnvironment()`, making the
|
||||
// child Environment accessible to the inspector as if it were a Node.js Worker.
|
||||
diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc
|
||||
index a8661c3c2263fc62e55659310b8da12fc414361e..849442aa8c923808420cbc888befea7d3f1f4c1b 100644
|
||||
--- a/src/node_main_instance.cc
|
||||
+++ b/src/node_main_instance.cc
|
||||
@@ -157,7 +157,8 @@ NodeMainInstance::CreateMainEnvironment(int* exit_code) {
|
||||
exec_args_,
|
||||
&(snapshot_data_->env_info),
|
||||
EnvironmentFlags::kDefaultFlags,
|
||||
- {}));
|
||||
+ {},
|
||||
+ nullptr));
|
||||
context = Context::FromSnapshot(isolate_,
|
||||
SnapshotData::kNodeMainContextIndex,
|
||||
{DeserializeNodeInternalFields, env.get()})
|
||||
+// Run initialization for the environment.
|
||||
+//
|
||||
+// The |preload| function, usually used by embedders to inject scripts,
|
||||
+// will be run by Node.js before Node.js executes the entry point.
|
||||
+// The function is guaranteed to run before the user land module loader running
|
||||
+// any user code, so it is safe to assume that at this point, no user code has
|
||||
+// been run yet.
|
||||
+// The function will be executed with preload(process, require), and the passed
|
||||
+// require function has access to internal Node.js modules. There is no
|
||||
+// stability guarantee about the internals exposed to the internal require
|
||||
+// function. Expect breakages when updating Node.js versions if the embedder
|
||||
+// imports internal modules with the internal require function.
|
||||
+// Worker threads created in the environment will also respect The |preload|
|
||||
+// function, so make sure the function is thread-safe.
|
||||
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment(
|
||||
Environment* env,
|
||||
- StartExecutionCallback cb);
|
||||
+ StartExecutionCallback cb,
|
||||
+ EmbedderPreloadCallback preload = nullptr);
|
||||
NODE_EXTERN v8::MaybeLocal<v8::Value> LoadEnvironment(
|
||||
Environment* env,
|
||||
- const char* main_script_source_utf8);
|
||||
+ const char* main_script_source_utf8,
|
||||
+ EmbedderPreloadCallback preload = nullptr);
|
||||
NODE_EXTERN void FreeEnvironment(Environment* env);
|
||||
|
||||
// Set a callback that is called when process.exit() is called from JS,
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 7ad8d80faee840e4dd224d946871b2ff08b0c23c..25842fd531fc7e1485bcd75f1f92aa9bc0640862 100644
|
||||
--- a/src/node_options.cc
|
||||
@@ -234,24 +170,28 @@ index 7ad8d80faee840e4dd224d946871b2ff08b0c23c..25842fd531fc7e1485bcd75f1f92aa9b
|
||||
}
|
||||
|
||||
diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc
|
||||
index bfa048a4a8aa183e747dec84b11b1c1d847db2dd..b8337e68cb946366b2dff78bbd12ce5473ee166c 100644
|
||||
index bfa048a4a8aa183e747dec84b11b1c1d847db2dd..970cec6c6e9c5e9646bfd758a2cf908e6b5799cf 100644
|
||||
--- a/src/node_snapshotable.cc
|
||||
+++ b/src/node_snapshotable.cc
|
||||
@@ -1462,6 +1462,13 @@ void SerializeSnapshotableObjects(Realm* realm,
|
||||
@@ -1462,6 +1462,17 @@ void SerializeSnapshotableObjects(Realm* realm,
|
||||
|
||||
namespace mksnapshot {
|
||||
|
||||
+static void RunEmbedderPreload(const FunctionCallbackInfo<Value>& args) {
|
||||
+void RunEmbedderPreload(const FunctionCallbackInfo<Value>& args) {
|
||||
+ Environment* env = Environment::GetCurrent(args);
|
||||
+ CHECK(env->embedder_preload());
|
||||
+ CHECK_EQ(args.Length(), 2);
|
||||
+ env->embedder_preload()(env, args[0], args[1]);
|
||||
+ Local<Value> process_obj = args[0];
|
||||
+ Local<Value> require_fn = args[1];
|
||||
+ CHECK(process_obj->IsObject());
|
||||
+ CHECK(require_fn->IsFunction());
|
||||
+ env->embedder_preload()(env, process_obj, require_fn);
|
||||
+}
|
||||
+
|
||||
void CompileSerializeMain(const FunctionCallbackInfo<Value>& args) {
|
||||
CHECK(args[0]->IsString());
|
||||
Local<String> filename = args[0].As<String>();
|
||||
@@ -1515,6 +1522,7 @@ void Initialize(Local<Object> target,
|
||||
@@ -1515,6 +1526,7 @@ void Initialize(Local<Object> target,
|
||||
Local<Value> unused,
|
||||
Local<Context> context,
|
||||
void* priv) {
|
||||
@@ -259,7 +199,7 @@ index bfa048a4a8aa183e747dec84b11b1c1d847db2dd..b8337e68cb946366b2dff78bbd12ce54
|
||||
SetMethod(context, target, "compileSerializeMain", CompileSerializeMain);
|
||||
SetMethod(context, target, "setSerializeCallback", SetSerializeCallback);
|
||||
SetMethod(context, target, "setDeserializeCallback", SetDeserializeCallback);
|
||||
@@ -1525,6 +1533,7 @@ void Initialize(Local<Object> target,
|
||||
@@ -1525,6 +1537,7 @@ void Initialize(Local<Object> target,
|
||||
}
|
||||
|
||||
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||
@@ -268,7 +208,7 @@ index bfa048a4a8aa183e747dec84b11b1c1d847db2dd..b8337e68cb946366b2dff78bbd12ce54
|
||||
registry->Register(SetSerializeCallback);
|
||||
registry->Register(SetDeserializeCallback);
|
||||
diff --git a/src/node_worker.cc b/src/node_worker.cc
|
||||
index 6a49144ec4f2059fe75983609b0768e4c2b1817d..dc2eb247b011f9cb1945c173c49e029f068ef103 100644
|
||||
index 6a49144ec4f2059fe75983609b0768e4c2b1817d..13b0445370c70cf3765a4af44336c16ac2e1035d 100644
|
||||
--- a/src/node_worker.cc
|
||||
+++ b/src/node_worker.cc
|
||||
@@ -60,6 +60,7 @@ Worker::Worker(Environment* env,
|
||||
@@ -279,16 +219,20 @@ index 6a49144ec4f2059fe75983609b0768e4c2b1817d..dc2eb247b011f9cb1945c173c49e029f
|
||||
snapshot_data_(snapshot_data) {
|
||||
Debug(this, "Creating new worker instance with thread id %llu",
|
||||
thread_id_.id);
|
||||
@@ -333,7 +334,8 @@ void Worker::Run() {
|
||||
std::move(exec_argv_),
|
||||
static_cast<EnvironmentFlags::Flags>(environment_flags_),
|
||||
thread_id_,
|
||||
- std::move(inspector_parent_handle_)));
|
||||
+ std::move(inspector_parent_handle_),
|
||||
+ std::move(embedder_preload_)));
|
||||
if (is_stopped()) return;
|
||||
CHECK_NOT_NULL(env_);
|
||||
env_->set_env_vars(std::move(env_vars_));
|
||||
@@ -354,8 +355,12 @@ void Worker::Run() {
|
||||
}
|
||||
|
||||
Debug(this, "Created message port for worker %llu", thread_id_.id);
|
||||
- if (LoadEnvironment(env_.get(), StartExecutionCallback{}).IsEmpty())
|
||||
+ if (LoadEnvironment(env_.get(),
|
||||
+ StartExecutionCallback{},
|
||||
+ std::move(embedder_preload_))
|
||||
+ .IsEmpty()) {
|
||||
return;
|
||||
+ }
|
||||
|
||||
Debug(this, "Loaded environment for worker %llu", thread_id_.id);
|
||||
}
|
||||
diff --git a/src/node_worker.h b/src/node_worker.h
|
||||
index a77c416735a79feb3f54e40d72a98c8903a20ccd..deab68576f6330f8bcfb4703fd05dbb9c515e473 100644
|
||||
--- a/src/node_worker.h
|
||||
@@ -302,7 +246,7 @@ index a77c416735a79feb3f54e40d72a98c8903a20ccd..deab68576f6330f8bcfb4703fd05dbb9
|
||||
// A raw flag that is used by creator and worker threads to
|
||||
// sync up on pre-mature termination of worker - while in the
|
||||
diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc
|
||||
index 547c8ddbffe243113bfe47a51072bb8f1541b94f..19ef2c2a083f908267e6a9365e77b20d46a3feec 100644
|
||||
index 547c8ddbffe243113bfe47a51072bb8f1541b94f..9f1fec4c4e47376c3b93a549f5c7ddf8e7ed3ac6 100644
|
||||
--- a/test/cctest/test_environment.cc
|
||||
+++ b/test/cctest/test_environment.cc
|
||||
@@ -749,3 +749,31 @@ TEST_F(EnvironmentTest, RequestInterruptAtExit) {
|
||||
@@ -320,20 +264,20 @@ index 547c8ddbffe243113bfe47a51072bb8f1541b94f..19ef2c2a083f908267e6a9365e77b20d
|
||||
+ v8::Local<v8::Value> require) {
|
||||
+ CHECK(process->IsObject());
|
||||
+ CHECK(require->IsFunction());
|
||||
+ process.As<v8::Object>()->Set(
|
||||
+ env->context(),
|
||||
+ v8::String::NewFromUtf8Literal(env->isolate(), "prop"),
|
||||
+ v8::String::NewFromUtf8Literal(env->isolate(), "preload")).Check();
|
||||
+ process.As<v8::Object>()
|
||||
+ ->Set(env->context(),
|
||||
+ v8::String::NewFromUtf8Literal(env->isolate(), "prop"),
|
||||
+ v8::String::NewFromUtf8Literal(env->isolate(), "preload"))
|
||||
+ .Check();
|
||||
+ };
|
||||
+
|
||||
+ std::unique_ptr<node::Environment, decltype(&node::FreeEnvironment)> env(
|
||||
+ node::CreateEnvironment(isolate_data_, context, {}, {},
|
||||
+ node::EnvironmentFlags::kDefaultFlags, {}, {},
|
||||
+ preload),
|
||||
+ node::CreateEnvironment(isolate_data_, context, {}, {}),
|
||||
+ node::FreeEnvironment);
|
||||
+
|
||||
+ v8::Local<v8::Value> main_ret =
|
||||
+ node::LoadEnvironment(env.get(), "return process.prop;").ToLocalChecked();
|
||||
+ node::LoadEnvironment(env.get(), "return process.prop;", preload)
|
||||
+ .ToLocalChecked();
|
||||
+ node::Utf8Value main_ret_str(isolate_, main_ret);
|
||||
+ EXPECT_EQ(std::string(*main_ret_str), "preload");
|
||||
+}
|
||||
|
||||
@@ -7,3 +7,8 @@ merged_turboshaft_fix_structuraloptimization_because_of_ignored.patch
|
||||
cherry-pick-389ea9be7d68.patch
|
||||
cherry-pick-46cb67e3b296.patch
|
||||
cherry-pick-78dd4b31847a.patch
|
||||
merged_wasm_add_bounds_check_in_tier-up_of_wasm-to-js_wrapper.patch
|
||||
merged_parser_fix_home_object_proxy_to_work_off-thread.patch
|
||||
merged_wasm_check_for_type-definition_count_limit.patch
|
||||
merged_runtime_recreate_enum_cache_on_map_update_if_any_previous.patch
|
||||
merged_wasm_check_the_cached_memory_for_growability.patch
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shu-yu Guo <syg@chromium.org>
|
||||
Date: Thu, 7 Mar 2024 14:55:28 -0800
|
||||
Subject: Merged: [parser] Fix home object proxy to work off-thread
|
||||
|
||||
Because the home object has special scope lookup rules due to class
|
||||
heritage position, VariableProxies of the home object are currently
|
||||
directly created on the correct scope during parsing. However, during
|
||||
off-thread parsing the main thread is parked, and the correct scope
|
||||
may try to dereference a main-thread Handle.
|
||||
|
||||
This CL moves the logic into ResolveVariable instead, which happens
|
||||
during postprocessing, with the main thread unparked.
|
||||
|
||||
Fixed: chromium:327740539
|
||||
|
||||
(cherry picked from commit 8f477f936c9b9e6b4c9f35a8ccc5e65bd4cb7f4e)
|
||||
|
||||
Change-Id: I16805ad35f5d70d1acadaf1f5440dfc159dbfa6c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5363634
|
||||
Reviewed-by: Deepti Gandluri <gdeepti@chromium.org>
|
||||
Commit-Queue: Shu-yu Guo <syg@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/12.2@{#44}
|
||||
Cr-Branched-From: 6eb5a9616aa6f8c705217aeb7c7ab8c037a2f676-refs/heads/12.2.281@{#1}
|
||||
Cr-Branched-From: 44cf56d850167c6988522f8981730462abc04bcc-refs/heads/main@{#91934}
|
||||
|
||||
diff --git a/src/ast/ast.h b/src/ast/ast.h
|
||||
index cf9d52eeed67a3d7685916987b540950385f98ce..7bb30723607ec9a3cef9d45b032c3edfa55bdc9c 100644
|
||||
--- a/src/ast/ast.h
|
||||
+++ b/src/ast/ast.h
|
||||
@@ -1534,6 +1534,12 @@ class VariableProxy final : public Expression {
|
||||
bit_field_ = IsRemovedFromUnresolvedField::update(bit_field_, true);
|
||||
}
|
||||
|
||||
+ bool is_home_object() const { return IsHomeObjectField::decode(bit_field_); }
|
||||
+
|
||||
+ void set_is_home_object() {
|
||||
+ bit_field_ = IsHomeObjectField::update(bit_field_, true);
|
||||
+ }
|
||||
+
|
||||
// Provides filtered access to the unresolved variable proxy threaded list.
|
||||
struct UnresolvedNext {
|
||||
static VariableProxy** filter(VariableProxy** t) {
|
||||
@@ -1565,6 +1571,7 @@ class VariableProxy final : public Expression {
|
||||
bit_field_ |= IsAssignedField::encode(false) |
|
||||
IsResolvedField::encode(false) |
|
||||
IsRemovedFromUnresolvedField::encode(false) |
|
||||
+ IsHomeObjectField::encode(false) |
|
||||
HoleCheckModeField::encode(HoleCheckMode::kElided);
|
||||
}
|
||||
|
||||
@@ -1574,7 +1581,8 @@ class VariableProxy final : public Expression {
|
||||
using IsResolvedField = IsAssignedField::Next<bool, 1>;
|
||||
using IsRemovedFromUnresolvedField = IsResolvedField::Next<bool, 1>;
|
||||
using IsNewTargetField = IsRemovedFromUnresolvedField::Next<bool, 1>;
|
||||
- using HoleCheckModeField = IsNewTargetField::Next<HoleCheckMode, 1>;
|
||||
+ using IsHomeObjectField = IsNewTargetField::Next<bool, 1>;
|
||||
+ using HoleCheckModeField = IsHomeObjectField::Next<HoleCheckMode, 1>;
|
||||
|
||||
union {
|
||||
const AstRawString* raw_name_; // if !is_resolved_
|
||||
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
|
||||
index 003bd0f27368a26893c1e2a16a7a914036ec6114..3441594155696d327dce2886519afdfb9a462125 100644
|
||||
--- a/src/ast/scopes.cc
|
||||
+++ b/src/ast/scopes.cc
|
||||
@@ -491,7 +491,6 @@ Scope* Scope::DeserializeScopeChain(IsolateT* isolate, Zone* zone,
|
||||
if (cache_scope_found) {
|
||||
outer_scope->set_deserialized_scope_uses_external_cache();
|
||||
} else {
|
||||
- DCHECK(!cache_scope_found);
|
||||
cache_scope_found =
|
||||
outer_scope->is_declaration_scope() && !outer_scope->is_eval_scope();
|
||||
}
|
||||
@@ -970,9 +969,14 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
|
||||
DCHECK(!cache->deserialized_scope_uses_external_cache());
|
||||
// The case where where the cache can be another scope is when the cache scope
|
||||
// is the last scope that doesn't use an external cache.
|
||||
+ //
|
||||
+ // The one exception to this is when looking up the home object, which may
|
||||
+ // skip multiple scopes that don't use an external cache (e.g., several arrow
|
||||
+ // functions).
|
||||
DCHECK_IMPLIES(
|
||||
cache != this,
|
||||
- cache->outer_scope()->deserialized_scope_uses_external_cache());
|
||||
+ cache->outer_scope()->deserialized_scope_uses_external_cache() ||
|
||||
+ cache->GetHomeObjectScope() == this);
|
||||
DCHECK_NULL(cache->variables_.Lookup(name));
|
||||
DisallowGarbageCollection no_gc;
|
||||
|
||||
@@ -2282,7 +2286,33 @@ Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
|
||||
|
||||
void Scope::ResolveVariable(VariableProxy* proxy) {
|
||||
DCHECK(!proxy->is_resolved());
|
||||
- Variable* var = Lookup<kParsedScope>(proxy, this, nullptr);
|
||||
+ Variable* var;
|
||||
+ if (V8_UNLIKELY(proxy->is_home_object())) {
|
||||
+ // VariableProxies of the home object cannot be resolved like a normal
|
||||
+ // variable. Consider the case of a super.property usage in heritage
|
||||
+ // position:
|
||||
+ //
|
||||
+ // class C extends super.foo { m() { super.bar(); } }
|
||||
+ //
|
||||
+ // The super.foo property access is logically nested under C's class scope,
|
||||
+ // which also has a home object due to its own method m's usage of
|
||||
+ // super.bar(). However, super.foo must resolve super in C's outer scope.
|
||||
+ //
|
||||
+ // Because of the above, start resolving home objects directly at the home
|
||||
+ // object scope instead of the current scope.
|
||||
+ Scope* scope = GetDeclarationScope()->GetHomeObjectScope();
|
||||
+ DCHECK_NOT_NULL(scope);
|
||||
+ if (scope->scope_info_.is_null()) {
|
||||
+ var = Lookup<kParsedScope>(proxy, scope, nullptr);
|
||||
+ } else {
|
||||
+ Scope* entry_cache = scope->deserialized_scope_uses_external_cache()
|
||||
+ ? GetNonEvalDeclarationScope()
|
||||
+ : scope;
|
||||
+ var = Lookup<kDeserializedScope>(proxy, scope, nullptr, entry_cache);
|
||||
+ }
|
||||
+ } else {
|
||||
+ var = Lookup<kParsedScope>(proxy, this, nullptr);
|
||||
+ }
|
||||
DCHECK_NOT_NULL(var);
|
||||
ResolveTo(proxy, var);
|
||||
}
|
||||
@@ -2752,48 +2782,6 @@ int Scope::ContextLocalCount() const {
|
||||
(is_function_var_in_context ? 1 : 0);
|
||||
}
|
||||
|
||||
-VariableProxy* Scope::NewHomeObjectVariableProxy(AstNodeFactory* factory,
|
||||
- const AstRawString* name,
|
||||
- int start_pos) {
|
||||
- // VariableProxies of the home object cannot be resolved like a normal
|
||||
- // variable. Consider the case of a super.property usage in heritage position:
|
||||
- //
|
||||
- // class C extends super.foo { m() { super.bar(); } }
|
||||
- //
|
||||
- // The super.foo property access is logically nested under C's class scope,
|
||||
- // which also has a home object due to its own method m's usage of
|
||||
- // super.bar(). However, super.foo must resolve super in C's outer scope.
|
||||
- //
|
||||
- // Because of the above, home object VariableProxies are always made directly
|
||||
- // on the Scope that needs the home object instead of the innermost scope.
|
||||
- DCHECK(needs_home_object());
|
||||
- if (!scope_info_.is_null()) {
|
||||
- // This is a lazy compile, so the home object's context slot is already
|
||||
- // known.
|
||||
- Variable* home_object = variables_.Lookup(name);
|
||||
- if (home_object == nullptr) {
|
||||
- VariableLookupResult lookup_result;
|
||||
- int index = scope_info_->ContextSlotIndex(name->string(), &lookup_result);
|
||||
- DCHECK_GE(index, 0);
|
||||
- bool was_added;
|
||||
- home_object = variables_.Declare(zone(), this, name, lookup_result.mode,
|
||||
- NORMAL_VARIABLE, lookup_result.init_flag,
|
||||
- lookup_result.maybe_assigned_flag,
|
||||
- IsStaticFlag::kNotStatic, &was_added);
|
||||
- DCHECK(was_added);
|
||||
- home_object->AllocateTo(VariableLocation::CONTEXT, index);
|
||||
- }
|
||||
- return factory->NewVariableProxy(home_object, start_pos);
|
||||
- }
|
||||
- // This is not a lazy compile. Add the unresolved home object VariableProxy to
|
||||
- // the unresolved list of the home object scope, which is not necessarily the
|
||||
- // innermost scope.
|
||||
- VariableProxy* proxy =
|
||||
- factory->NewVariableProxy(name, NORMAL_VARIABLE, start_pos);
|
||||
- AddUnresolved(proxy);
|
||||
- return proxy;
|
||||
-}
|
||||
-
|
||||
bool IsComplementaryAccessorPair(VariableMode a, VariableMode b) {
|
||||
switch (a) {
|
||||
case VariableMode::kPrivateGetterOnly:
|
||||
diff --git a/src/ast/scopes.h b/src/ast/scopes.h
|
||||
index b4c2e8b2136813985231a722c6dbcd26e2c17336..751aaee3d11ecc0da71e2171dd42ed4b85d00219 100644
|
||||
--- a/src/ast/scopes.h
|
||||
+++ b/src/ast/scopes.h
|
||||
@@ -603,10 +603,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
needs_home_object_ = true;
|
||||
}
|
||||
|
||||
- VariableProxy* NewHomeObjectVariableProxy(AstNodeFactory* factory,
|
||||
- const AstRawString* name,
|
||||
- int start_pos);
|
||||
-
|
||||
bool RemoveInnerScope(Scope* inner_scope) {
|
||||
DCHECK_NOT_NULL(inner_scope);
|
||||
if (inner_scope == inner_scope_) {
|
||||
@@ -865,7 +861,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
|
||||
FunctionKind function_kind() const { return function_kind_; }
|
||||
|
||||
// Inform the scope that the corresponding code uses "super".
|
||||
- Scope* RecordSuperPropertyUsage() {
|
||||
+ void RecordSuperPropertyUsage() {
|
||||
DCHECK(IsConciseMethod(function_kind()) ||
|
||||
IsAccessorFunction(function_kind()) ||
|
||||
IsClassConstructor(function_kind()));
|
||||
@@ -873,7 +869,6 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
|
||||
Scope* home_object_scope = GetHomeObjectScope();
|
||||
DCHECK_NOT_NULL(home_object_scope);
|
||||
home_object_scope->set_needs_home_object();
|
||||
- return home_object_scope;
|
||||
}
|
||||
|
||||
bool uses_super_property() const { return uses_super_property_; }
|
||||
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
|
||||
index 66e531dfe786dd7e3ea8c52cdf58214405f4f91e..714406f6aa56fc06e93309b2bf83d93e9431dbc8 100644
|
||||
--- a/src/parsing/parser-base.h
|
||||
+++ b/src/parsing/parser-base.h
|
||||
@@ -3800,9 +3800,9 @@ ParserBase<Impl>::ParseSuperExpression() {
|
||||
impl()->ReportMessage(MessageTemplate::kOptionalChainingNoSuper);
|
||||
return impl()->FailureExpression();
|
||||
}
|
||||
- Scope* home_object_scope = scope->RecordSuperPropertyUsage();
|
||||
+ scope->RecordSuperPropertyUsage();
|
||||
UseThis();
|
||||
- return impl()->NewSuperPropertyReference(home_object_scope, pos);
|
||||
+ return impl()->NewSuperPropertyReference(pos);
|
||||
}
|
||||
// super() is only allowed in derived constructor. new super() is never
|
||||
// allowed; it's reported as an error by
|
||||
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
||||
index da16f85234d7c06bcd57423325edd6a7049baed8..972ccba46da36cbc5bef8e65b15aeb0326039ad1 100644
|
||||
--- a/src/parsing/parser.cc
|
||||
+++ b/src/parsing/parser.cc
|
||||
@@ -300,18 +300,17 @@ Expression* Parser::NewThrowError(Runtime::FunctionId id,
|
||||
return factory()->NewThrow(call_constructor, pos);
|
||||
}
|
||||
|
||||
-Expression* Parser::NewSuperPropertyReference(Scope* home_object_scope,
|
||||
- int pos) {
|
||||
+Expression* Parser::NewSuperPropertyReference(int pos) {
|
||||
const AstRawString* home_object_name;
|
||||
if (IsStatic(scope()->GetReceiverScope()->function_kind())) {
|
||||
home_object_name = ast_value_factory_->dot_static_home_object_string();
|
||||
} else {
|
||||
home_object_name = ast_value_factory_->dot_home_object_string();
|
||||
}
|
||||
- return factory()->NewSuperPropertyReference(
|
||||
- home_object_scope->NewHomeObjectVariableProxy(factory(), home_object_name,
|
||||
- pos),
|
||||
- pos);
|
||||
+
|
||||
+ VariableProxy* proxy = NewUnresolved(home_object_name, pos);
|
||||
+ proxy->set_is_home_object();
|
||||
+ return factory()->NewSuperPropertyReference(proxy, pos);
|
||||
}
|
||||
|
||||
Expression* Parser::NewSuperCallReference(int pos) {
|
||||
diff --git a/src/parsing/parser.h b/src/parsing/parser.h
|
||||
index 8aede5d6a2cd38b2ad02fa2d7542ea8163c29aa9..0e92f0350b5989781bda0eeb9746cfa18cd5e179 100644
|
||||
--- a/src/parsing/parser.h
|
||||
+++ b/src/parsing/parser.h
|
||||
@@ -798,7 +798,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
return factory()->NewThisExpression(pos);
|
||||
}
|
||||
|
||||
- Expression* NewSuperPropertyReference(Scope* home_object_scope, int pos);
|
||||
+ Expression* NewSuperPropertyReference(int pos);
|
||||
Expression* NewSuperCallReference(int pos);
|
||||
Expression* NewTargetExpression(int pos);
|
||||
Expression* ImportMetaExpression(int pos);
|
||||
diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h
|
||||
index 6c4996bd06be782bd0f767a2bfb6d413cfc1ae82..2ca6b9ac407b0862d82be466eec624280b241b09 100644
|
||||
--- a/src/parsing/preparser.h
|
||||
+++ b/src/parsing/preparser.h
|
||||
@@ -1536,8 +1536,7 @@ class PreParser : public ParserBase<PreParser> {
|
||||
return PreParserExpression::This();
|
||||
}
|
||||
|
||||
- V8_INLINE PreParserExpression
|
||||
- NewSuperPropertyReference(Scope* home_object_scope, int pos) {
|
||||
+ V8_INLINE PreParserExpression NewSuperPropertyReference(int pos) {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Darius Mercadier <dmercadier@chromium.org>
|
||||
Date: Fri, 22 Mar 2024 17:55:04 +0100
|
||||
Subject: Merged: [runtime] Recreate enum cache on map update if any previous
|
||||
map had one
|
||||
|
||||
If any previous map in the transition tree had an enum cache, then we
|
||||
recreate one when updating the map.
|
||||
|
||||
Bug: 330760873
|
||||
(cherry picked from commit 807cf7d0b7d96212c98ed2119e07f9b2c6a23f61)
|
||||
|
||||
Change-Id: Ia9ea4cf17fef60166a0c037318eb539866aac37a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5401859
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Commit-Queue: Igor Sheludko <ishell@chromium.org>
|
||||
Auto-Submit: Darius Mercadier <dmercadier@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/12.2@{#52}
|
||||
Cr-Branched-From: 6eb5a9616aa6f8c705217aeb7c7ab8c037a2f676-refs/heads/12.2.281@{#1}
|
||||
Cr-Branched-From: 44cf56d850167c6988522f8981730462abc04bcc-refs/heads/main@{#91934}
|
||||
|
||||
diff --git a/src/objects/map-updater.cc b/src/objects/map-updater.cc
|
||||
index 613a4921637b113121e06a470ef996974577f58b..1d649373274bd41c4346f3955efde8583fb923fc 100644
|
||||
--- a/src/objects/map-updater.cc
|
||||
+++ b/src/objects/map-updater.cc
|
||||
@@ -1038,14 +1038,21 @@ MapUpdater::State MapUpdater::ConstructNewMap() {
|
||||
Handle<Map> new_map =
|
||||
Map::AddMissingTransitions(isolate_, split_map, new_descriptors);
|
||||
|
||||
+ bool had_any_enum_cache =
|
||||
+ split_map->instance_descriptors(isolate_)
|
||||
+ ->enum_cache()
|
||||
+ ->keys()
|
||||
+ ->length() > 0 ||
|
||||
+ old_descriptors_->enum_cache()->keys()->length() > 0;
|
||||
+
|
||||
// Deprecated part of the transition tree is no longer reachable, so replace
|
||||
// current instance descriptors in the "survived" part of the tree with
|
||||
// the new descriptors to maintain descriptors sharing invariant.
|
||||
split_map->ReplaceDescriptors(isolate_, *new_descriptors);
|
||||
|
||||
- // If the old descriptors had an enum cache, make sure the new ones do too.
|
||||
- if (old_descriptors_->enum_cache()->keys()->length() > 0 &&
|
||||
- new_map->NumberOfEnumerableProperties() > 0) {
|
||||
+ // If the old descriptors had an enum cache (or if {split_map}'s descriptors
|
||||
+ // had one), make sure the new ones do too.
|
||||
+ if (had_any_enum_cache && new_map->NumberOfEnumerableProperties() > 0) {
|
||||
FastKeyAccumulator::InitializeFastPropertyEnumCache(
|
||||
isolate_, new_map, new_map->NumberOfEnumerableProperties());
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Haas <ahaas@chromium.org>
|
||||
Date: Tue, 20 Feb 2024 16:27:22 +0100
|
||||
Subject: Merged: [wasm] Add bounds check in tier-up of wasm-to-js wrapper
|
||||
|
||||
The entry index in the WasmApiFunctionRef was used to look for the given
|
||||
WasmApiFunctionRef in the indirect function tables, but it was not
|
||||
considered that the indirect function tables can have different lengths.
|
||||
|
||||
R=clemensb@chromium.org
|
||||
|
||||
Bug: 325893559
|
||||
|
||||
(cherry picked from commit 7330f46163e8a2c10a3d40ecbf554656f0ac55e8)
|
||||
|
||||
Change-Id: I52355890e21490c75566216985680c64e0b0db75
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5323850
|
||||
Commit-Queue: Andreas Haas <ahaas@chromium.org>
|
||||
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/12.2@{#38}
|
||||
Cr-Branched-From: 6eb5a9616aa6f8c705217aeb7c7ab8c037a2f676-refs/heads/12.2.281@{#1}
|
||||
Cr-Branched-From: 44cf56d850167c6988522f8981730462abc04bcc-refs/heads/main@{#91934}
|
||||
|
||||
diff --git a/src/runtime/runtime-wasm.cc b/src/runtime/runtime-wasm.cc
|
||||
index 60d9e0516847bba3b74e3b50774cbcf115158428..88e12b8b62cbe79763c2f73ec1b8f7176e3ec980 100644
|
||||
--- a/src/runtime/runtime-wasm.cc
|
||||
+++ b/src/runtime/runtime-wasm.cc
|
||||
@@ -532,7 +532,8 @@ RUNTIME_FUNCTION(Runtime_TierUpWasmToJSWrapper) {
|
||||
for (int table_index = 0; table_index < table_count; ++table_index) {
|
||||
Handle<WasmIndirectFunctionTable> table =
|
||||
instance->GetIndirectFunctionTable(isolate, table_index);
|
||||
- if (table->refs()->get(entry_index) == *ref) {
|
||||
+ if (entry_index < table->refs()->length() &&
|
||||
+ table->refs()->get(entry_index) == *ref) {
|
||||
table->targets()
|
||||
->set<ExternalPointerTag::kWasmIndirectFunctionTargetTag>(
|
||||
entry_index, isolate, wasm_code->instruction_start());
|
||||
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Manos Koukoutos <manoskouk@chromium.org>
|
||||
Date: Thu, 21 Mar 2024 11:38:08 +0100
|
||||
Subject: Merged: [wasm] Check for type-definition count limit
|
||||
|
||||
(cherry picked from commit b852ad701db21d6db5b34e66f4ec1cdccd2ec4d4)
|
||||
|
||||
Bug: chromium:330575498
|
||||
Change-Id: I395f0ed6d823b7d1e139da6551486e3627d65724
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5378419
|
||||
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Auto-Submit: Manos Koukoutos <manoskouk@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#92941}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5380190
|
||||
Reviewed-by: Francis McCabe <fgm@chromium.org>
|
||||
Commit-Queue: Adam Klein <adamk@chromium.org>
|
||||
Reviewed-by: Adam Klein <adamk@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/12.2@{#50}
|
||||
Cr-Branched-From: 6eb5a9616aa6f8c705217aeb7c7ab8c037a2f676-refs/heads/12.2.281@{#1}
|
||||
Cr-Branched-From: 44cf56d850167c6988522f8981730462abc04bcc-refs/heads/main@{#91934}
|
||||
|
||||
diff --git a/src/wasm/module-decoder-impl.h b/src/wasm/module-decoder-impl.h
|
||||
index 97554288b55d1690999ace9fa17409dd357a89d0..75ca3a630a290d9a6615be1ccf5ec02ab2a0994a 100644
|
||||
--- a/src/wasm/module-decoder-impl.h
|
||||
+++ b/src/wasm/module-decoder-impl.h
|
||||
@@ -687,6 +687,11 @@ class ModuleDecoderImpl : public Decoder {
|
||||
}
|
||||
} else {
|
||||
if (tracer_) tracer_->TypeOffset(pc_offset());
|
||||
+ if (initial_size + 1 > kV8MaxWasmTypes) {
|
||||
+ errorf(pc(), "Type definition count exceeds maximum %zu",
|
||||
+ kV8MaxWasmTypes);
|
||||
+ return;
|
||||
+ }
|
||||
// Similarly to above, we need to resize types for a group of size 1.
|
||||
module_->types.resize(initial_size + 1);
|
||||
module_->isorecursive_canonical_type_ids.resize(initial_size + 1);
|
||||
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Clemens Backes <clemensb@chromium.org>
|
||||
Date: Wed, 17 Jan 2024 09:41:46 +0000
|
||||
Subject: Merged: [wasm] Check the cached memory for growability
|
||||
|
||||
Instead of always checking memory 0, do check if the actually cached
|
||||
memory is growable.
|
||||
|
||||
R=jkummerow@chromium.org
|
||||
|
||||
(cherry picked from commit 1285ee44a9e5207a8c1302bfaa745ca06f0a90a8)
|
||||
Bug: chromium:1518257
|
||||
|
||||
Change-Id: Ic415e281d85bb979f1fd27aa5e14a5fcc52ffbf1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5232161
|
||||
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Commit-Queue: Clemens Backes <clemensb@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/12.0@{#36}
|
||||
Cr-Branched-From: ed7b4caf1fb8184ad9e24346c84424055d4d430a-refs/heads/12.0.267@{#1}
|
||||
Cr-Branched-From: 210e75b19db4352c9b78dce0bae11c2dc3077df4-refs/heads/main@{#90651}
|
||||
|
||||
diff --git a/src/wasm/graph-builder-interface.cc b/src/wasm/graph-builder-interface.cc
|
||||
index 4cbd8a9032622382c15321c82409db6e3da3a511..2ed779148501c45db238e805eb3c4a8c7009bdc9 100644
|
||||
--- a/src/wasm/graph-builder-interface.cc
|
||||
+++ b/src/wasm/graph-builder-interface.cc
|
||||
@@ -265,17 +265,18 @@ class WasmGraphBuildingInterface {
|
||||
}
|
||||
}
|
||||
|
||||
- // Load the instance cache entries into the Ssa Environment.
|
||||
+ // Load the instance cache entries into the SSA Environment.
|
||||
void LoadInstanceCacheIntoSsa(SsaEnv* ssa_env) {
|
||||
builder_->InitInstanceCache(&ssa_env->instance_cache);
|
||||
}
|
||||
|
||||
- // Reload the instance cache entries into the Ssa Environment, if memory can
|
||||
+ // Reload the instance cache entries into the SSA Environment, if memory can
|
||||
// actually grow.
|
||||
void ReloadInstanceCacheIntoSsa(SsaEnv* ssa_env, const WasmModule* module) {
|
||||
- if (module->memories.empty()) return;
|
||||
- const WasmMemory* memory0 = &module->memories[0];
|
||||
- if (memory0->initial_pages == memory0->maximum_pages) return;
|
||||
+ if (!builder_->has_cached_memory()) return;
|
||||
+ const WasmMemory* cached_memory =
|
||||
+ &module->memories[builder_->cached_memory_index()];
|
||||
+ if (cached_memory->initial_pages == cached_memory->maximum_pages) return;
|
||||
LoadInstanceCacheIntoSsa(ssa_env);
|
||||
}
|
||||
|
||||
@@ -2,3 +2,6 @@ fix_fallback_to_x11_capturer_on_wayland.patch
|
||||
fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch
|
||||
fix_check_pipewire_init_before_creating_generic_capturer.patch
|
||||
pipewire_capturer_make_restore_tokens_re-usable_more_than_one_time.patch
|
||||
tighten_som_dchecks_to_checks_in_vp9_packetization.patch
|
||||
m122_merge_limit_max_frame_size_in_dav1d_decoder.patch
|
||||
revert_2_m120_jseptransportcontroller_remove_raw_pointers_to.patch
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Silkin <ssilkin@webrtc.org>
|
||||
Date: Wed, 21 Feb 2024 10:35:54 +0100
|
||||
Subject: Limit max frame size in DAV1D decoder
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
(cherry picked from commit 74a4038eaddcac773b9fc172ad446df6eb704b11)
|
||||
|
||||
Bug: chromium:325284120
|
||||
Change-Id: Iea0aea0a17bb0b1f73b3c1cbd408b7a6cd2b216e
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/340180
|
||||
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
|
||||
Reviewed-by: Erik Språng <sprang@webrtc.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#41776}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/340580
|
||||
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
|
||||
Commit-Queue: Erik Språng <sprang@webrtc.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6261@{#1}
|
||||
Cr-Branched-From: be2786cd2383b7ec5d158add166275d19e246763-refs/heads/main@{#41596}
|
||||
|
||||
diff --git a/modules/video_coding/codecs/av1/dav1d_decoder.cc b/modules/video_coding/codecs/av1/dav1d_decoder.cc
|
||||
index 3100c0d41bf429fa55984e07f137983d24ef58f8..77c360b9449ff784a15f0ba6e132fe8511d537ae 100644
|
||||
--- a/modules/video_coding/codecs/av1/dav1d_decoder.cc
|
||||
+++ b/modules/video_coding/codecs/av1/dav1d_decoder.cc
|
||||
@@ -87,6 +87,8 @@ bool Dav1dDecoder::Configure(const Settings& settings) {
|
||||
s.n_threads = std::max(2, settings.number_of_cores());
|
||||
s.max_frame_delay = 1; // For low latency decoding.
|
||||
s.all_layers = 0; // Don't output a frame for every spatial layer.
|
||||
+ // Limit max frame size to avoid OOM'ing fuzzers. crbug.com/325284120.
|
||||
+ s.frame_size_limit = 16384 * 16384;
|
||||
s.operating_point = 31; // Decode all operating points.
|
||||
|
||||
return dav1d_open(&context_, &s) == 0;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,103 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Erik=20Spr=C3=A5ng?= <sprang@webrtc.org>
|
||||
Date: Fri, 19 Jan 2024 16:59:01 +0100
|
||||
Subject: Tighten som DCHECKs to CHECKs in VP9 packetization.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
(cherry picked from commit 6a992129fb0dede4a8fbdaf5de43abaf43c20299)
|
||||
|
||||
No-Try: True
|
||||
Bug: chromium:1518991, chromium:1518994
|
||||
Change-Id: I47f68ba6aaf4874fd952332bf213e3a1e0389268
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/335241
|
||||
Auto-Submit: Erik Språng <sprang@webrtc.org>
|
||||
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
|
||||
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#41580}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/338640
|
||||
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
|
||||
Commit-Queue: Erik Språng <sprang@webrtc.org>
|
||||
Cr-Commit-Position: refs/branch-heads/6167@{#6}
|
||||
Cr-Branched-From: ece5cb83715dea85617114b6d4e981fdee2623ba-refs/heads/main@{#41315}
|
||||
|
||||
diff --git a/modules/rtp_rtcp/source/rtp_format_vp9.cc b/modules/rtp_rtcp/source/rtp_format_vp9.cc
|
||||
index 15e059e85c8968c8ed72efa6b17ac998b5597f45..9ad4aa97c34aabe761739045662adc6374e3dc69 100644
|
||||
--- a/modules/rtp_rtcp/source/rtp_format_vp9.cc
|
||||
+++ b/modules/rtp_rtcp/source/rtp_format_vp9.cc
|
||||
@@ -94,8 +94,8 @@ size_t RefIndicesLength(const RTPVideoHeaderVP9& hdr) {
|
||||
if (!hdr.inter_pic_predicted || !hdr.flexible_mode)
|
||||
return 0;
|
||||
|
||||
- RTC_DCHECK_GT(hdr.num_ref_pics, 0U);
|
||||
- RTC_DCHECK_LE(hdr.num_ref_pics, kMaxVp9RefPics);
|
||||
+ RTC_CHECK_GT(hdr.num_ref_pics, 0U);
|
||||
+ RTC_CHECK_LE(hdr.num_ref_pics, kMaxVp9RefPics);
|
||||
return hdr.num_ref_pics;
|
||||
}
|
||||
|
||||
@@ -123,9 +123,9 @@ size_t SsDataLength(const RTPVideoHeaderVP9& hdr) {
|
||||
if (!hdr.ss_data_available)
|
||||
return 0;
|
||||
|
||||
- RTC_DCHECK_GT(hdr.num_spatial_layers, 0U);
|
||||
- RTC_DCHECK_LE(hdr.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
- RTC_DCHECK_LE(hdr.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
+ RTC_CHECK_GT(hdr.num_spatial_layers, 0U);
|
||||
+ RTC_CHECK_LE(hdr.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
+ RTC_CHECK_LE(hdr.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
size_t length = 1; // V
|
||||
if (hdr.spatial_layer_resolution_present) {
|
||||
length += 4 * hdr.num_spatial_layers; // Y
|
||||
@@ -136,7 +136,7 @@ size_t SsDataLength(const RTPVideoHeaderVP9& hdr) {
|
||||
// N_G
|
||||
length += hdr.gof.num_frames_in_gof; // T, U, R
|
||||
for (size_t i = 0; i < hdr.gof.num_frames_in_gof; ++i) {
|
||||
- RTC_DCHECK_LE(hdr.gof.num_ref_pics[i], kMaxVp9RefPics);
|
||||
+ RTC_CHECK_LE(hdr.gof.num_ref_pics[i], kMaxVp9RefPics);
|
||||
length += hdr.gof.num_ref_pics[i]; // R times
|
||||
}
|
||||
return length;
|
||||
@@ -248,9 +248,9 @@ bool WriteRefIndices(const RTPVideoHeaderVP9& vp9,
|
||||
// +-+-+-+-+-+-+-+-+ -| -|
|
||||
//
|
||||
bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) {
|
||||
- RTC_DCHECK_GT(vp9.num_spatial_layers, 0U);
|
||||
- RTC_DCHECK_LE(vp9.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
- RTC_DCHECK_LE(vp9.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
+ RTC_CHECK_GT(vp9.num_spatial_layers, 0U);
|
||||
+ RTC_CHECK_LE(vp9.num_spatial_layers, kMaxVp9NumberOfSpatialLayers);
|
||||
+ RTC_CHECK_LE(vp9.gof.num_frames_in_gof, kMaxVp9FramesInGof);
|
||||
bool g_bit = vp9.gof.num_frames_in_gof > 0;
|
||||
|
||||
RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.num_spatial_layers - 1, 3));
|
||||
@@ -288,6 +288,8 @@ bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) {
|
||||
// current API to invoke SVC is not flexible enough.
|
||||
RTPVideoHeaderVP9 RemoveInactiveSpatialLayers(
|
||||
const RTPVideoHeaderVP9& original_header) {
|
||||
+ RTC_CHECK_LE(original_header.num_spatial_layers,
|
||||
+ kMaxVp9NumberOfSpatialLayers);
|
||||
RTPVideoHeaderVP9 hdr(original_header);
|
||||
if (original_header.first_active_layer == 0)
|
||||
return hdr;
|
||||
@@ -314,7 +316,7 @@ RtpPacketizerVp9::RtpPacketizerVp9(rtc::ArrayView<const uint8_t> payload,
|
||||
header_size_(PayloadDescriptorLengthMinusSsData(hdr_)),
|
||||
first_packet_extra_header_size_(SsDataLength(hdr_)),
|
||||
remaining_payload_(payload) {
|
||||
- RTC_DCHECK_EQ(hdr_.first_active_layer, 0);
|
||||
+ RTC_CHECK_EQ(hdr_.first_active_layer, 0);
|
||||
|
||||
limits.max_payload_len -= header_size_;
|
||||
limits.first_packet_reduction_len += first_packet_extra_header_size_;
|
||||
@@ -357,8 +359,8 @@ bool RtpPacketizerVp9::NextPacket(RtpPacketToSend* packet) {
|
||||
|
||||
// Ensure end_of_picture is always set on top spatial layer when it is not
|
||||
// dropped.
|
||||
- RTC_DCHECK(hdr_.spatial_idx < hdr_.num_spatial_layers - 1 ||
|
||||
- hdr_.end_of_picture);
|
||||
+ RTC_CHECK(hdr_.spatial_idx < hdr_.num_spatial_layers - 1 ||
|
||||
+ hdr_.end_of_picture);
|
||||
|
||||
packet->SetMarker(layer_end && hdr_.end_of_picture);
|
||||
return true;
|
||||
@@ -3,19 +3,30 @@
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from lib import git
|
||||
from lib.patches import patch_from_dir
|
||||
|
||||
THREEWAY = "ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES" in os.environ
|
||||
|
||||
def apply_patches(dirs):
|
||||
threeway = os.environ.get("ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES")
|
||||
for patch_dir, repo in dirs.items():
|
||||
if os.path.exists(repo):
|
||||
git.import_patches(repo=repo, patch_data=patch_from_dir(patch_dir),
|
||||
threeway=threeway is not None,
|
||||
committer_name="Electron Scripts", committer_email="scripts@electron")
|
||||
def apply_patches(target):
|
||||
repo = target.get('repo')
|
||||
if not os.path.exists(repo):
|
||||
warnings.warn('repo not found: %s' % repo)
|
||||
return
|
||||
patch_dir = target.get('patch_dir')
|
||||
git.import_patches(
|
||||
committer_email="scripts@electron",
|
||||
committer_name="Electron Scripts",
|
||||
patch_data=patch_from_dir(patch_dir),
|
||||
repo=repo,
|
||||
threeway=THREEWAY,
|
||||
)
|
||||
|
||||
def apply_config(config):
|
||||
for target in config:
|
||||
apply_patches(target)
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='Apply Electron patches')
|
||||
@@ -26,9 +37,8 @@ def parse_args():
|
||||
|
||||
|
||||
def main():
|
||||
configs = parse_args().config
|
||||
for config_json in configs:
|
||||
apply_patches(json.load(config_json))
|
||||
for config_json in parse_args().config:
|
||||
apply_config(json.load(config_json))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -3,14 +3,27 @@
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from lib import git
|
||||
|
||||
|
||||
def export_patches(dirs, dry_run):
|
||||
for patch_dir, repo in dirs.items():
|
||||
if os.path.exists(repo):
|
||||
git.export_patches(repo=repo, out_dir=patch_dir, dry_run=dry_run)
|
||||
def export_patches(target, dry_run):
|
||||
repo = target.get('repo')
|
||||
if not os.path.exists(repo):
|
||||
warnings.warn('repo not found: %s' % repo)
|
||||
return
|
||||
git.export_patches(
|
||||
dry_run=dry_run,
|
||||
grep=target.get('grep'),
|
||||
out_dir=target.get('patch_dir'),
|
||||
repo=repo
|
||||
)
|
||||
|
||||
|
||||
def export_config(config, dry_run):
|
||||
for target in config:
|
||||
export_patches(target, dry_run)
|
||||
|
||||
|
||||
def parse_args():
|
||||
@@ -28,7 +41,7 @@ def main():
|
||||
configs = parse_args().config
|
||||
dry_run = parse_args().dry_run
|
||||
for config_json in configs:
|
||||
export_patches(json.load(config_json), dry_run)
|
||||
export_config(json.load(config_json), dry_run)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -10,13 +10,15 @@ def main(argv):
|
||||
parser.add_argument("-o", "--output",
|
||||
help="directory into which exported patches will be written",
|
||||
required=True)
|
||||
parser.add_argument("--grep",
|
||||
help="only export patches matching a keyword")
|
||||
parser.add_argument("patch_range",
|
||||
nargs='?',
|
||||
help="range of patches to export. Defaults to all commits since the "
|
||||
"most recent tag or remote branch.")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
git.export_patches('.', args.output, patch_range=args.patch_range)
|
||||
git.export_patches('.', args.output, patch_range=args.patch_range, grep=args.grep)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -15,6 +15,12 @@ import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append(SCRIPT_DIR)
|
||||
|
||||
from patches import PATCH_FILENAME_PREFIX, is_patch_location_line
|
||||
|
||||
UPSTREAM_HEAD='refs/patches/upstream-head'
|
||||
|
||||
def is_repo_root(path):
|
||||
path_exists = os.path.exists(path)
|
||||
@@ -77,14 +83,10 @@ def am(repo, patch_data, threeway=False, directory=None, exclude=None,
|
||||
proc.returncode))
|
||||
|
||||
|
||||
def import_patches(repo, **kwargs):
|
||||
def import_patches(repo, ref=UPSTREAM_HEAD, **kwargs):
|
||||
"""same as am(), but we save the upstream HEAD so we can refer to it when we
|
||||
later export patches"""
|
||||
update_ref(
|
||||
repo=repo,
|
||||
ref='refs/patches/upstream-head',
|
||||
newvalue='HEAD'
|
||||
)
|
||||
update_ref(repo=repo, ref=ref, newvalue='HEAD')
|
||||
am(repo=repo, **kwargs)
|
||||
|
||||
|
||||
@@ -94,32 +96,18 @@ def update_ref(repo, ref, newvalue):
|
||||
return subprocess.check_call(args)
|
||||
|
||||
|
||||
def get_upstream_head(repo):
|
||||
args = [
|
||||
'git',
|
||||
'-C',
|
||||
repo,
|
||||
'rev-parse',
|
||||
'--verify',
|
||||
'refs/patches/upstream-head',
|
||||
]
|
||||
def get_commit_for_ref(repo, ref):
|
||||
args = ['git', '-C', repo, 'rev-parse', '--verify', ref]
|
||||
return subprocess.check_output(args).decode('utf-8').strip()
|
||||
|
||||
def get_commit_count(repo, commit_range):
|
||||
args = [
|
||||
'git',
|
||||
'-C',
|
||||
repo,
|
||||
'rev-list',
|
||||
'--count',
|
||||
commit_range
|
||||
]
|
||||
args = ['git', '-C', repo, 'rev-list', '--count', commit_range]
|
||||
return int(subprocess.check_output(args).decode('utf-8').strip())
|
||||
|
||||
def guess_base_commit(repo):
|
||||
def guess_base_commit(repo, ref):
|
||||
"""Guess which commit the patches might be based on"""
|
||||
try:
|
||||
upstream_head = get_upstream_head(repo)
|
||||
upstream_head = get_commit_for_ref(repo, ref)
|
||||
num_commits = get_commit_count(repo, upstream_head + '..')
|
||||
return [upstream_head, num_commits]
|
||||
except subprocess.CalledProcessError:
|
||||
@@ -183,6 +171,16 @@ def split_patches(patch_data):
|
||||
patches[-1].append(line)
|
||||
return patches
|
||||
|
||||
def filter_patches(patches, key):
|
||||
"""Return patches that include the specified key"""
|
||||
if key is None:
|
||||
return patches
|
||||
matches = []
|
||||
for patch in patches:
|
||||
if any(key in line for line in patch):
|
||||
matches.append(patch)
|
||||
continue
|
||||
return matches
|
||||
|
||||
def munge_subject_to_filename(subject):
|
||||
"""Derive a suitable filename from a commit's subject"""
|
||||
@@ -195,8 +193,8 @@ def get_file_name(patch):
|
||||
"""Return the name of the file to which the patch should be written"""
|
||||
file_name = None
|
||||
for line in patch:
|
||||
if line.startswith('Patch-Filename: '):
|
||||
file_name = line[len('Patch-Filename: '):]
|
||||
if line.startswith(PATCH_FILENAME_PREFIX):
|
||||
file_name = line[len(PATCH_FILENAME_PREFIX):]
|
||||
break
|
||||
# If no patch-filename header, munge the subject.
|
||||
if not file_name:
|
||||
@@ -209,19 +207,18 @@ def get_file_name(patch):
|
||||
|
||||
def join_patch(patch):
|
||||
"""Joins and formats patch contents"""
|
||||
return ''.join(remove_patch_filename(patch)).rstrip('\n') + '\n'
|
||||
return ''.join(remove_patch_location(patch)).rstrip('\n') + '\n'
|
||||
|
||||
|
||||
def remove_patch_filename(patch):
|
||||
"""Strip out the Patch-Filename trailer from a patch's message body"""
|
||||
def remove_patch_location(patch):
|
||||
"""Strip out the patch location lines from a patch's message body"""
|
||||
force_keep_next_line = False
|
||||
n = len(patch)
|
||||
for i, l in enumerate(patch):
|
||||
is_patchfilename = l.startswith('Patch-Filename: ')
|
||||
next_is_patchfilename = i < len(patch) - 1 and patch[i + 1].startswith(
|
||||
'Patch-Filename: '
|
||||
)
|
||||
skip_line = is_patch_location_line(l)
|
||||
skip_next = i < n - 1 and is_patch_location_line(patch[i + 1])
|
||||
if not force_keep_next_line and (
|
||||
is_patchfilename or (next_is_patchfilename and len(l.rstrip()) == 0)
|
||||
skip_line or (skip_next and len(l.rstrip()) == 0)
|
||||
):
|
||||
pass # drop this line
|
||||
else:
|
||||
@@ -237,18 +234,24 @@ def to_utf8(patch):
|
||||
return unicode(patch, "utf-8")
|
||||
|
||||
|
||||
def export_patches(repo, out_dir, patch_range=None, dry_run=False):
|
||||
def export_patches(repo, out_dir,
|
||||
patch_range=None, ref=UPSTREAM_HEAD,
|
||||
dry_run=False, grep=None):
|
||||
if not os.path.exists(repo):
|
||||
sys.stderr.write(
|
||||
"Skipping patches in {} because it does not exist.\n".format(repo)
|
||||
)
|
||||
return
|
||||
if patch_range is None:
|
||||
patch_range, num_patches = guess_base_commit(repo)
|
||||
patch_range, num_patches = guess_base_commit(repo, ref)
|
||||
sys.stderr.write("Exporting {} patches in {} since {}\n".format(
|
||||
num_patches, repo, patch_range[0:7]))
|
||||
patch_data = format_patch(repo, patch_range)
|
||||
patches = split_patches(patch_data)
|
||||
if grep:
|
||||
olen = len(patches)
|
||||
patches = filter_patches(patches, grep)
|
||||
sys.stderr.write("Exporting {} of {} patches\n".format(len(patches), olen))
|
||||
|
||||
try:
|
||||
os.mkdir(out_dir)
|
||||
|
||||
@@ -3,19 +3,27 @@
|
||||
import codecs
|
||||
import os
|
||||
|
||||
PATCH_DIR_PREFIX = "Patch-Dir: "
|
||||
PATCH_FILENAME_PREFIX = "Patch-Filename: "
|
||||
PATCH_LINE_PREFIXES = (PATCH_DIR_PREFIX, PATCH_FILENAME_PREFIX)
|
||||
|
||||
|
||||
def is_patch_location_line(line):
|
||||
return line.startswith(PATCH_LINE_PREFIXES)
|
||||
|
||||
def read_patch(patch_dir, patch_filename):
|
||||
"""Read a patch from |patch_dir/filename| and amend the commit message with
|
||||
metadata about the patch file it came from."""
|
||||
ret = []
|
||||
added_filename_line = False
|
||||
added_patch_location = False
|
||||
patch_path = os.path.join(patch_dir, patch_filename)
|
||||
with codecs.open(patch_path, encoding='utf-8') as f:
|
||||
for l in f.readlines():
|
||||
line_has_correct_start = l.startswith('diff -') or l.startswith('---')
|
||||
if not added_filename_line and line_has_correct_start:
|
||||
ret.append('Patch-Filename: {}\n'.format(patch_filename))
|
||||
added_filename_line = True
|
||||
if not added_patch_location and line_has_correct_start:
|
||||
ret.append('{}{}\n'.format(PATCH_DIR_PREFIX, patch_dir))
|
||||
ret.append('{}{}\n'.format(PATCH_FILENAME_PREFIX, patch_filename))
|
||||
added_patch_location = True
|
||||
ret.append(l)
|
||||
return ''.join(ret)
|
||||
|
||||
|
||||
@@ -201,10 +201,9 @@ const LINTERS = [{
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const config = JSON.parse(fs.readFileSync(patchesConfig, 'utf8'));
|
||||
for (const key of Object.keys(config)) {
|
||||
for (const target of JSON.parse(fs.readFileSync(patchesConfig, 'utf8'))) {
|
||||
// The directory the config points to should exist
|
||||
const targetPatchesDir = path.resolve(__dirname, '../../..', key);
|
||||
const targetPatchesDir = path.resolve(__dirname, '../../..', target.patch_dir);
|
||||
if (!fs.existsSync(targetPatchesDir)) {
|
||||
console.error(`target patch directory: "${targetPatchesDir}" does not exist`);
|
||||
process.exit(1);
|
||||
|
||||
@@ -14,7 +14,9 @@ from lib.patches import patch_from_dir
|
||||
|
||||
|
||||
def patched_file_paths(patches_config):
|
||||
for patch_dir, repo in patches_config.items():
|
||||
for target in patches_config:
|
||||
patch_dir = target.get('patch_dir')
|
||||
repo = target.get('repo')
|
||||
for line in patch_from_dir(patch_dir).split("\n"):
|
||||
if line.startswith("+++"):
|
||||
yield posixpath.join(repo, line[6:])
|
||||
|
||||
@@ -26,7 +26,9 @@ const getHeaders = (filePath: string, fileName: string) => {
|
||||
if (!extension) {
|
||||
throw new Error(`Failed to get headers for extensionless file: ${fileName}`);
|
||||
}
|
||||
console.log(`About to get size of ${filePath}`);
|
||||
const size = fs.statSync(filePath).size;
|
||||
console.log(`Got size of ${filePath}: ${size}`);
|
||||
const options: Record<string, string> = {
|
||||
json: 'text/json',
|
||||
zip: 'application/zip',
|
||||
@@ -45,10 +47,13 @@ const uploadUrl = `https://uploads.github.com/repos/electron/${targetRepo}/relea
|
||||
let retry = 0;
|
||||
|
||||
function uploadToGitHub () {
|
||||
console.log(`in uploadToGitHub for ${filePath}, ${fileName}`);
|
||||
const fileData = fs.createReadStream(filePath);
|
||||
console.log(`in uploadToGitHub, created readstream for ${filePath}`);
|
||||
octokit.repos.uploadReleaseAsset({
|
||||
url: uploadUrl,
|
||||
headers: getHeaders(filePath, fileName),
|
||||
data: fs.createReadStream(filePath) as any,
|
||||
data: fileData as any,
|
||||
name: fileName,
|
||||
owner: 'electron',
|
||||
repo: targetRepo,
|
||||
|
||||
@@ -363,10 +363,13 @@ def upload_io_to_github(release, filename, filepath, version):
|
||||
(filename))
|
||||
script_path = os.path.join(
|
||||
ELECTRON_DIR, 'script', 'release', 'uploaders', 'upload-to-github.ts')
|
||||
upload_gh_output = execute([TS_NODE, script_path, filepath, filename,
|
||||
str(release['id']), version])
|
||||
upload_process = subprocess.Popen([TS_NODE, script_path, filepath, filename,
|
||||
str(release['id']), version], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
if is_verbose_mode():
|
||||
print(upload_gh_output)
|
||||
for c in iter(lambda: upload_process.stdout.read(1), b""):
|
||||
sys.stdout.buffer.write(c)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def upload_sha256_checksum(version, file_path, key_prefix=None):
|
||||
|
||||
@@ -259,8 +259,7 @@ int NodeMain(int argc, char* argv[]) {
|
||||
env = node::CreateEnvironment(
|
||||
isolate_data, isolate->GetCurrentContext(), result->args(),
|
||||
result->exec_args(),
|
||||
static_cast<node::EnvironmentFlags::Flags>(env_flags), {}, {},
|
||||
&OnNodePreload);
|
||||
static_cast<node::EnvironmentFlags::Flags>(env_flags));
|
||||
CHECK_NE(nullptr, env);
|
||||
|
||||
node::SetIsolateUpForNode(isolate);
|
||||
@@ -285,7 +284,7 @@ int NodeMain(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
v8::HandleScope scope(isolate);
|
||||
node::LoadEnvironment(env, node::StartExecutionCallback{});
|
||||
node::LoadEnvironment(env, node::StartExecutionCallback{}, &OnNodePreload);
|
||||
|
||||
// Potential reasons we get Nothing here may include: the env
|
||||
// is stopping, or the user hooks process.emit('exit').
|
||||
|
||||
@@ -1224,13 +1224,10 @@ void App::ImportCertificate(gin_helper::ErrorThrower thrower,
|
||||
return;
|
||||
}
|
||||
|
||||
auto* browser_context = ElectronBrowserContext::From("", false);
|
||||
if (!certificate_manager_model_) {
|
||||
CertificateManagerModel::Create(
|
||||
browser_context,
|
||||
base::BindOnce(&App::OnCertificateManagerModelCreated,
|
||||
base::Unretained(this), std::move(options),
|
||||
std::move(callback)));
|
||||
CertificateManagerModel::Create(base::BindOnce(
|
||||
&App::OnCertificateManagerModelCreated, base::Unretained(this),
|
||||
std::move(options), std::move(callback)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1683,7 +1680,7 @@ gin::ObjectTemplateBuilder App::GetObjectTemplateBuilder(v8::Isolate* isolate) {
|
||||
.SetMethod("setBadgeCount",
|
||||
base::BindRepeating(&Browser::SetBadgeCount, browser))
|
||||
.SetMethod("getBadgeCount",
|
||||
base::BindRepeating(&Browser::GetBadgeCount, browser))
|
||||
base::BindRepeating(&Browser::badge_count, browser))
|
||||
.SetMethod("getLoginItemSettings", &App::GetLoginItemSettings)
|
||||
.SetMethod("setLoginItemSettings",
|
||||
base::BindRepeating(&Browser::SetLoginItemSettings, browser))
|
||||
|
||||
@@ -159,8 +159,7 @@ v8::Local<v8::Promise> Debugger::SendCommand(gin::Arguments* args) {
|
||||
request.Set("sessionId", session_id);
|
||||
}
|
||||
|
||||
std::string json_args;
|
||||
base::JSONWriter::Write(request, &json_args);
|
||||
const auto json_args = base::WriteJson(request).value_or("");
|
||||
agent_host_->DispatchProtocolMessage(
|
||||
this, base::as_bytes(base::make_span(json_args)));
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ bool IsEncryptionAvailable() {
|
||||
return OSCrypt::IsEncryptionAvailable() ||
|
||||
(use_password_v10 &&
|
||||
static_cast<BrowserProcessImpl*>(g_browser_process)
|
||||
->GetLinuxStorageBackend() == "basic_text");
|
||||
->linux_storage_backend() == "basic_text");
|
||||
#else
|
||||
return OSCrypt::IsEncryptionAvailable();
|
||||
#endif
|
||||
@@ -46,7 +46,7 @@ std::string GetSelectedLinuxBackend() {
|
||||
if (!Browser::Get()->is_ready())
|
||||
return "unknown";
|
||||
return static_cast<BrowserProcessImpl*>(g_browser_process)
|
||||
->GetLinuxStorageBackend();
|
||||
->linux_storage_backend();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -845,7 +845,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
session_.Reset(isolate, session.ToV8());
|
||||
|
||||
std::unique_ptr<content::WebContents> web_contents;
|
||||
if (IsGuest()) {
|
||||
if (is_guest()) {
|
||||
scoped_refptr<content::SiteInstance> site_instance =
|
||||
content::SiteInstance::CreateForURL(session->browser_context(),
|
||||
GURL("chrome-guest://fake-host"));
|
||||
@@ -915,7 +915,7 @@ void WebContents::InitWithSessionAndOptions(
|
||||
const gin_helper::Dictionary& options) {
|
||||
Observe(owned_web_contents.get());
|
||||
InitWithWebContents(std::move(owned_web_contents), session->browser_context(),
|
||||
IsGuest());
|
||||
is_guest());
|
||||
|
||||
inspectable_web_contents_->GetView()->SetDelegate(this);
|
||||
|
||||
@@ -975,7 +975,7 @@ void WebContents::InitWithSessionAndOptions(
|
||||
|
||||
SetUserAgent(GetBrowserContext()->GetUserAgent());
|
||||
|
||||
if (IsGuest()) {
|
||||
if (is_guest()) {
|
||||
NativeWindow* owner_window = nullptr;
|
||||
if (embedder_) {
|
||||
// New WebContents's owner_window is the embedder's owner_window.
|
||||
@@ -1010,7 +1010,7 @@ void WebContents::InitWithExtensionView(v8::Isolate* isolate,
|
||||
// Allow toggling DevTools for background pages
|
||||
Observe(web_contents);
|
||||
InitWithWebContents(std::unique_ptr<content::WebContents>(web_contents),
|
||||
GetBrowserContext(), IsGuest());
|
||||
GetBrowserContext(), is_guest());
|
||||
inspectable_web_contents_->GetView()->SetDelegate(this);
|
||||
}
|
||||
#endif
|
||||
@@ -1056,7 +1056,7 @@ WebContents::~WebContents() {
|
||||
|
||||
// For guest view based on OOPIF, the WebContents is released by the embedder
|
||||
// frame, and we need to clear the reference to the memory.
|
||||
bool not_owned_by_this = IsGuest() && attached_;
|
||||
bool not_owned_by_this = is_guest() && attached_;
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
// And background pages are owned by extensions::ExtensionHost.
|
||||
if (type_ == Type::kBackgroundPage)
|
||||
@@ -1086,7 +1086,7 @@ void WebContents::DeleteThisIfAlive() {
|
||||
void WebContents::Destroy() {
|
||||
// The content::WebContents should be destroyed asynchronously when possible
|
||||
// as user may choose to destroy WebContents during an event of it.
|
||||
if (Browser::Get()->is_shutting_down() || IsGuest()) {
|
||||
if (Browser::Get()->is_shutting_down() || is_guest()) {
|
||||
DeleteThisIfAlive();
|
||||
} else {
|
||||
content::GetUIThreadTaskRunner({})->PostTask(
|
||||
@@ -1300,7 +1300,7 @@ void WebContents::CloseContents(content::WebContents* source) {
|
||||
observer.OnCloseContents();
|
||||
|
||||
// This is handled by the embedder frame.
|
||||
if (!IsGuest())
|
||||
if (!is_guest())
|
||||
Destroy();
|
||||
}
|
||||
|
||||
@@ -1617,7 +1617,7 @@ void WebContents::HandleNewRenderFrame(
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
||||
if (web_preferences) {
|
||||
auto maybe_color = web_preferences->GetBackgroundColor();
|
||||
bool guest = IsGuest() || type_ == Type::kBrowserView;
|
||||
bool guest = is_guest() || type_ == Type::kBrowserView;
|
||||
|
||||
// If webPreferences has no color stored we need to explicitly set guest
|
||||
// webContents background color to transparent.
|
||||
@@ -2146,7 +2146,7 @@ void WebContents::DidFinishNavigation(
|
||||
Emit("did-navigate", url, http_response_code, http_status_text);
|
||||
}
|
||||
}
|
||||
if (IsGuest())
|
||||
if (is_guest())
|
||||
Emit("load-commit", url, is_main_frame);
|
||||
} else {
|
||||
auto url = navigation_handle->GetURL();
|
||||
@@ -2351,10 +2351,6 @@ base::ProcessId WebContents::GetOSProcessID() const {
|
||||
return base::GetProcId(process_handle);
|
||||
}
|
||||
|
||||
WebContents::Type WebContents::GetType() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool WebContents::Equal(const WebContents* web_contents) const {
|
||||
return ID() == web_contents->ID();
|
||||
}
|
||||
@@ -3303,7 +3299,7 @@ bool WebContents::IsFocused() const {
|
||||
if (!view)
|
||||
return false;
|
||||
|
||||
if (GetType() != Type::kBackgroundPage) {
|
||||
if (type() != Type::kBackgroundPage) {
|
||||
auto* window = web_contents()->GetNativeView()->GetToplevelWindow();
|
||||
if (window && !window->IsVisible())
|
||||
return false;
|
||||
@@ -3499,10 +3495,6 @@ void WebContents::OnCursorChanged(const ui::Cursor& cursor) {
|
||||
}
|
||||
}
|
||||
|
||||
bool WebContents::IsGuest() const {
|
||||
return type_ == Type::kWebView;
|
||||
}
|
||||
|
||||
void WebContents::AttachToIframe(content::WebContents* embedder_web_contents,
|
||||
int embedder_frame_id) {
|
||||
attached_ = true;
|
||||
@@ -4179,7 +4171,7 @@ void WebContents::UpdateHtmlApiFullscreen(bool fullscreen) {
|
||||
}
|
||||
|
||||
// Make sure all child webviews quit html fullscreen.
|
||||
if (!fullscreen && !IsGuest()) {
|
||||
if (!fullscreen && !is_guest()) {
|
||||
auto* manager = WebViewManager::GetWebViewManager(web_contents());
|
||||
manager->ForEachGuest(
|
||||
web_contents(), base::BindRepeating([](content::WebContents* guest) {
|
||||
@@ -4292,7 +4284,7 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
|
||||
.SetMethod("getZoomLevel", &WebContents::GetZoomLevel)
|
||||
.SetMethod("setZoomFactor", &WebContents::SetZoomFactor)
|
||||
.SetMethod("getZoomFactor", &WebContents::GetZoomFactor)
|
||||
.SetMethod("getType", &WebContents::GetType)
|
||||
.SetMethod("getType", &WebContents::type)
|
||||
.SetMethod("_getPreloadPaths", &WebContents::GetPreloadPaths)
|
||||
.SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
|
||||
@@ -164,7 +164,7 @@ class WebContents : public ExclusiveAccessContext,
|
||||
void SetBackgroundThrottling(bool allowed);
|
||||
int GetProcessID() const;
|
||||
base::ProcessId GetOSProcessID() const;
|
||||
Type GetType() const;
|
||||
[[nodiscard]] Type type() const { return type_; }
|
||||
bool Equal(const WebContents* web_contents) const;
|
||||
void LoadURL(const GURL& url, const gin_helper::Dictionary& options);
|
||||
void Reload();
|
||||
@@ -281,7 +281,7 @@ class WebContents : public ExclusiveAccessContext,
|
||||
v8::Local<v8::Promise> CapturePage(gin::Arguments* args);
|
||||
|
||||
// Methods for creating <webview>.
|
||||
bool IsGuest() const;
|
||||
[[nodiscard]] bool is_guest() const { return type_ == Type::kWebView; }
|
||||
void AttachToIframe(content::WebContents* embedder_web_contents,
|
||||
int embedder_frame_id);
|
||||
void DetachFromOuterFrame();
|
||||
|
||||
@@ -24,7 +24,7 @@ bool WebContents::IsFocused() const {
|
||||
if (!view)
|
||||
return false;
|
||||
|
||||
if (GetType() != Type::kBackgroundPage) {
|
||||
if (type() != Type::kBackgroundPage) {
|
||||
auto window = [web_contents()->GetNativeView().GetNativeNSView() window];
|
||||
// On Mac the render widget host view does not lose focus when the window
|
||||
// loses focus so check if the top level window is the key window.
|
||||
|
||||
@@ -159,10 +159,6 @@ void Browser::SetName(const std::string& name) {
|
||||
OverriddenApplicationName() = name;
|
||||
}
|
||||
|
||||
int Browser::GetBadgeCount() {
|
||||
return badge_count_;
|
||||
}
|
||||
|
||||
bool Browser::OpenFile(const std::string& file_path) {
|
||||
bool prevent_default = false;
|
||||
for (BrowserObserver& observer : observers_)
|
||||
|
||||
@@ -109,7 +109,7 @@ class Browser : public WindowListObserver {
|
||||
|
||||
// Set/Get the badge count.
|
||||
bool SetBadgeCount(absl::optional<int> count);
|
||||
int GetBadgeCount();
|
||||
[[nodiscard]] int badge_count() const { return badge_count_; }
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
struct LaunchItem {
|
||||
|
||||
@@ -333,10 +333,6 @@ void BrowserProcessImpl::SetLinuxStorageBackend(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& BrowserProcessImpl::GetLinuxStorageBackend() const {
|
||||
return selected_linux_storage_backend_;
|
||||
}
|
||||
#endif // BUILDFLAG(IS_LINUX)
|
||||
|
||||
void BrowserProcessImpl::SetApplicationLocale(const std::string& locale) {
|
||||
|
||||
@@ -59,7 +59,9 @@ class BrowserProcessImpl : public BrowserProcess {
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
void SetLinuxStorageBackend(os_crypt::SelectedLinuxBackend selected_backend);
|
||||
const std::string& GetLinuxStorageBackend() const;
|
||||
[[nodiscard]] const std::string& linux_storage_backend() const {
|
||||
return selected_linux_storage_backend_;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EndSession() override {}
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/resource_context.h"
|
||||
@@ -25,8 +23,7 @@ namespace {
|
||||
|
||||
net::NSSCertDatabase* g_nss_cert_database = nullptr;
|
||||
|
||||
net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
|
||||
content::ResourceContext* context,
|
||||
net::NSSCertDatabase* GetNSSCertDatabase(
|
||||
base::OnceCallback<void(net::NSSCertDatabase*)> callback) {
|
||||
// This initialization is not thread safe. This CHECK ensures that this code
|
||||
// is only run on a single thread.
|
||||
@@ -57,7 +54,7 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
|
||||
// \--------------------------------------v
|
||||
// CertificateManagerModel::GetCertDBOnIOThread
|
||||
// |
|
||||
// GetNSSCertDatabaseForResourceContext
|
||||
// GetNSSCertDatabase
|
||||
// |
|
||||
// CertificateManagerModel::DidGetCertDBOnIOThread
|
||||
// v--------------------------------------/
|
||||
@@ -68,12 +65,10 @@ net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
|
||||
// callback
|
||||
|
||||
// static
|
||||
void CertificateManagerModel::Create(content::BrowserContext* browser_context,
|
||||
CreationCallback callback) {
|
||||
void CertificateManagerModel::Create(CreationCallback callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
content::GetIOThreadTaskRunner({})->PostTask(
|
||||
FROM_HERE, base::BindOnce(&CertificateManagerModel::GetCertDBOnIOThread,
|
||||
browser_context->GetResourceContext(),
|
||||
std::move(callback)));
|
||||
}
|
||||
|
||||
@@ -151,16 +146,14 @@ void CertificateManagerModel::DidGetCertDBOnIOThread(
|
||||
}
|
||||
|
||||
// static
|
||||
void CertificateManagerModel::GetCertDBOnIOThread(
|
||||
content::ResourceContext* context,
|
||||
CreationCallback callback) {
|
||||
void CertificateManagerModel::GetCertDBOnIOThread(CreationCallback callback) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
auto split_callback = base::SplitOnceCallback(base::BindOnce(
|
||||
&CertificateManagerModel::DidGetCertDBOnIOThread, std::move(callback)));
|
||||
|
||||
net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext(
|
||||
context, std::move(split_callback.first));
|
||||
net::NSSCertDatabase* cert_db =
|
||||
GetNSSCertDatabase(std::move(split_callback.first));
|
||||
|
||||
// If the NSS database was already available, |cert_db| is non-null and
|
||||
// |did_get_cert_db_callback| has not been called. Call it explicitly.
|
||||
|
||||
@@ -13,11 +13,6 @@
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "net/cert/nss_cert_database.h"
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
class ResourceContext;
|
||||
} // namespace content
|
||||
|
||||
// CertificateManagerModel provides the data to be displayed in the certificate
|
||||
// manager dialog, and processes changes from the view.
|
||||
class CertificateManagerModel {
|
||||
@@ -26,10 +21,8 @@ class CertificateManagerModel {
|
||||
base::OnceCallback<void(std::unique_ptr<CertificateManagerModel>)>;
|
||||
|
||||
// Creates a CertificateManagerModel. The model will be passed to the callback
|
||||
// when it is ready. The caller must ensure the model does not outlive the
|
||||
// |browser_context|.
|
||||
static void Create(content::BrowserContext* browser_context,
|
||||
CreationCallback callback);
|
||||
// when it is ready.
|
||||
static void Create(CreationCallback callback);
|
||||
|
||||
// disable copy
|
||||
CertificateManagerModel(const CertificateManagerModel&) = delete;
|
||||
@@ -105,8 +98,7 @@ class CertificateManagerModel {
|
||||
CreationCallback callback);
|
||||
static void DidGetCertDBOnIOThread(CreationCallback callback,
|
||||
net::NSSCertDatabase* cert_db);
|
||||
static void GetCertDBOnIOThread(content::ResourceContext* context,
|
||||
CreationCallback callback);
|
||||
static void GetCertDBOnIOThread(CreationCallback callback);
|
||||
|
||||
raw_ptr<net::NSSCertDatabase> cert_db_;
|
||||
// Whether the certificate database has a public slot associated with the
|
||||
|
||||
@@ -602,10 +602,11 @@ ExtensionFunction::ResponseAction ScriptingExecuteScriptFunction::Run() {
|
||||
std::vector<std::string> string_args;
|
||||
string_args.reserve(injection_.args->size());
|
||||
for (const auto& arg : *injection_.args) {
|
||||
std::string json;
|
||||
if (!base::JSONWriter::Write(arg, &json))
|
||||
if (auto json = base::WriteJson(arg)) {
|
||||
string_args.push_back(std::move(*json));
|
||||
} else {
|
||||
return RespondNow(Error("Unserializable argument passed."));
|
||||
string_args.push_back(std::move(json));
|
||||
}
|
||||
}
|
||||
args_expression = base::JoinString(string_args, ",");
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
namespace electron {
|
||||
|
||||
NSArray* ListValueToNSArray(const base::Value::List& value) {
|
||||
std::string json;
|
||||
if (!base::JSONWriter::Write(base::ValueView{value}, &json))
|
||||
const auto json = base::WriteJson(value);
|
||||
if (!json.has_value())
|
||||
return nil;
|
||||
NSData* jsonData = [NSData dataWithBytes:json.c_str() length:json.length()];
|
||||
NSData* jsonData = [NSData dataWithBytes:json->data() length:json->size()];
|
||||
id obj = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:0
|
||||
error:nil];
|
||||
@@ -60,10 +60,10 @@ base::Value::List NSArrayToValue(NSArray* arr) {
|
||||
}
|
||||
|
||||
NSDictionary* DictionaryValueToNSDictionary(const base::Value::Dict& value) {
|
||||
std::string json;
|
||||
if (!base::JSONWriter::Write(base::ValueView{value}, &json))
|
||||
const auto json = base::WriteJson(value);
|
||||
if (!json.has_value())
|
||||
return nil;
|
||||
NSData* jsonData = [NSData dataWithBytes:json.c_str() length:json.length()];
|
||||
NSData* jsonData = [NSData dataWithBytes:json->data() length:json->size()];
|
||||
id obj = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:0
|
||||
error:nil];
|
||||
|
||||
@@ -516,14 +516,6 @@ bool NativeWindow::IsMenuBarVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
double NativeWindow::GetAspectRatio() {
|
||||
return aspect_ratio_;
|
||||
}
|
||||
|
||||
gfx::Size NativeWindow::GetAspectRatioExtraSize() {
|
||||
return aspect_ratio_extraSize_;
|
||||
}
|
||||
|
||||
void NativeWindow::SetAspectRatio(double aspect_ratio,
|
||||
const gfx::Size& extra_size) {
|
||||
aspect_ratio_ = aspect_ratio;
|
||||
@@ -761,6 +753,11 @@ int NativeWindow::NonClientHitTest(const gfx::Point& point) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// This is to disable dragging in HTML5 full screen mode.
|
||||
// Details: https://github.com/electron/electron/issues/41002
|
||||
if (GetWidget()->IsFullscreen())
|
||||
return HTNOWHERE;
|
||||
|
||||
for (auto* provider : draggable_region_providers_) {
|
||||
int hit = provider->NonClientHitTest(point);
|
||||
if (hit != HTNOWHERE)
|
||||
|
||||
@@ -264,8 +264,10 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual bool IsMenuBarVisible();
|
||||
|
||||
// Set the aspect ratio when resizing window.
|
||||
double GetAspectRatio();
|
||||
gfx::Size GetAspectRatioExtraSize();
|
||||
[[nodiscard]] double aspect_ratio() const { return aspect_ratio_; }
|
||||
[[nodiscard]] gfx::Size aspect_ratio_extra_size() const {
|
||||
return aspect_ratio_extraSize_;
|
||||
}
|
||||
virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size);
|
||||
|
||||
// File preview APIs.
|
||||
|
||||
@@ -622,7 +622,7 @@ bool NativeWindowMac::IsMaximized() {
|
||||
if (HasStyleMask(NSWindowStyleMaskResizable) != 0)
|
||||
return [window_ isZoomed];
|
||||
|
||||
NSRect rectScreen = GetAspectRatio() > 0.0
|
||||
NSRect rectScreen = aspect_ratio() > 0.0
|
||||
? default_frame_for_zoom()
|
||||
: [[NSScreen mainScreen] visibleFrame];
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ void AutofillPopup::SetItems(const std::vector<std::u16string>& values,
|
||||
void AutofillPopup::AcceptSuggestion(int index) {
|
||||
mojo::AssociatedRemote<mojom::ElectronAutofillAgent> autofill_agent;
|
||||
frame_host_->GetRemoteAssociatedInterfaces()->GetInterface(&autofill_agent);
|
||||
autofill_agent->AcceptDataListSuggestion(GetValueAt(index));
|
||||
autofill_agent->AcceptDataListSuggestion(value_at(index));
|
||||
}
|
||||
|
||||
void AutofillPopup::UpdatePopupBounds() {
|
||||
@@ -272,11 +272,10 @@ int AutofillPopup::GetDesiredPopupWidth() {
|
||||
int popup_width = element_bounds_.width();
|
||||
|
||||
for (size_t i = 0; i < values_.size(); ++i) {
|
||||
int row_size =
|
||||
kEndPadding + 2 * kPopupBorderThickness +
|
||||
gfx::GetStringWidth(GetValueAt(i), GetValueFontListForRow(i)) +
|
||||
gfx::GetStringWidth(GetLabelAt(i), GetLabelFontListForRow(i));
|
||||
if (!GetLabelAt(i).empty())
|
||||
int row_size = kEndPadding + 2 * kPopupBorderThickness +
|
||||
gfx::GetStringWidth(value_at(i), GetValueFontListForRow(i)) +
|
||||
gfx::GetStringWidth(label_at(i), GetLabelFontListForRow(i));
|
||||
if (!label_at(i).empty())
|
||||
row_size += kNamePadding + kEndPadding;
|
||||
|
||||
popup_width = std::max(popup_width, row_size);
|
||||
@@ -307,18 +306,6 @@ ui::ColorId AutofillPopup::GetBackgroundColorIDForRow(int index) const {
|
||||
: ui::kColorResultsTableNormalBackground;
|
||||
}
|
||||
|
||||
int AutofillPopup::GetLineCount() {
|
||||
return values_.size();
|
||||
}
|
||||
|
||||
std::u16string AutofillPopup::GetValueAt(int i) {
|
||||
return values_.at(i);
|
||||
}
|
||||
|
||||
std::u16string AutofillPopup::GetLabelAt(int i) {
|
||||
return labels_.at(i);
|
||||
}
|
||||
|
||||
int AutofillPopup::LineFromY(int y) const {
|
||||
int current_height = kPopupBorderThickness;
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ class AutofillPopup : public views::ViewObserver {
|
||||
const gfx::FontList& GetLabelFontListForRow(int index) const;
|
||||
ui::ColorId GetBackgroundColorIDForRow(int index) const;
|
||||
|
||||
int GetLineCount();
|
||||
std::u16string GetValueAt(int i);
|
||||
std::u16string GetLabelAt(int i);
|
||||
int line_count() const { return values_.size(); }
|
||||
const std::u16string& value_at(int i) const { return values_.at(i); }
|
||||
const std::u16string& label_at(int i) const { return labels_.at(i); }
|
||||
int LineFromY(int y) const;
|
||||
|
||||
int selected_index_;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
devtools_is_first_responder_ = NO;
|
||||
attached_to_window_ = NO;
|
||||
|
||||
if (inspectableWebContentsView_->inspectable_web_contents()->IsGuest()) {
|
||||
if (inspectableWebContentsView_->inspectable_web_contents()->is_guest()) {
|
||||
fake_view_ = [[NSView alloc] init];
|
||||
[fake_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[self addSubview:fake_view_];
|
||||
|
||||
@@ -493,8 +493,8 @@ NSArray* ConvertSharingItemToNS(const SharingItem& item) {
|
||||
if (menu_)
|
||||
return menu_;
|
||||
|
||||
if (model_ && model_->GetSharingItem()) {
|
||||
NSMenu* menu = [self createShareMenuForItem:*model_->GetSharingItem()];
|
||||
if (model_ && model_->sharing_item()) {
|
||||
NSMenu* menu = [self createShareMenuForItem:*model_->sharing_item()];
|
||||
menu_ = menu;
|
||||
} else {
|
||||
menu_ = [[NSMenu alloc] initWithTitle:@""];
|
||||
|
||||
@@ -80,7 +80,7 @@ using FullScreenTransitionState =
|
||||
- (NSRect)windowWillUseStandardFrame:(NSWindow*)window
|
||||
defaultFrame:(NSRect)frame {
|
||||
if (!shell_->zoom_to_page_width()) {
|
||||
if (shell_->GetAspectRatio() > 0.0)
|
||||
if (shell_->aspect_ratio() > 0.0)
|
||||
shell_->set_default_frame_for_zoom(frame);
|
||||
return frame;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ using FullScreenTransitionState =
|
||||
// Set the width. Don't touch y or height.
|
||||
frame.size.width = zoomed_width;
|
||||
|
||||
if (shell_->GetAspectRatio() > 0.0)
|
||||
if (shell_->aspect_ratio() > 0.0)
|
||||
shell_->set_default_frame_for_zoom(frame);
|
||||
|
||||
return frame;
|
||||
@@ -143,13 +143,12 @@ using FullScreenTransitionState =
|
||||
|
||||
- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize {
|
||||
NSSize newSize = frameSize;
|
||||
double aspectRatio = shell_->GetAspectRatio();
|
||||
NSWindow* window = shell_->GetNativeWindow().GetNativeNSWindow();
|
||||
|
||||
if (aspectRatio > 0.0) {
|
||||
gfx::Size windowSize = shell_->GetSize();
|
||||
gfx::Size contentSize = shell_->GetContentSize();
|
||||
gfx::Size extraSize = shell_->GetAspectRatioExtraSize();
|
||||
if (const double aspectRatio = shell_->aspect_ratio(); aspectRatio > 0.0) {
|
||||
const gfx::Size windowSize = shell_->GetSize();
|
||||
const gfx::Size contentSize = shell_->GetContentSize();
|
||||
const gfx::Size extraSize = shell_->aspect_ratio_extra_size();
|
||||
|
||||
double titleBarHeight = windowSize.height() - contentSize.height();
|
||||
double extraWidthPlusFrame =
|
||||
|
||||
@@ -99,11 +99,6 @@ bool ElectronMenuModel::GetSharingItemAt(size_t index,
|
||||
void ElectronMenuModel::SetSharingItem(SharingItem item) {
|
||||
sharing_item_.emplace(std::move(item));
|
||||
}
|
||||
|
||||
const absl::optional<ElectronMenuModel::SharingItem>&
|
||||
ElectronMenuModel::GetSharingItem() const {
|
||||
return sharing_item_;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ElectronMenuModel::MenuWillClose() {
|
||||
|
||||
@@ -98,7 +98,10 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
bool GetSharingItemAt(size_t index, SharingItem* item) const;
|
||||
// Set/Get the SharingItem of this menu.
|
||||
void SetSharingItem(SharingItem item);
|
||||
const absl::optional<SharingItem>& GetSharingItem() const;
|
||||
[[nodiscard]] const absl::optional<SharingItem>& sharing_item() const {
|
||||
return sharing_item_;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ui::SimpleMenuModel:
|
||||
|
||||
@@ -409,10 +409,6 @@ InspectableWebContentsDelegate* InspectableWebContents::GetDelegate() const {
|
||||
return delegate_;
|
||||
}
|
||||
|
||||
bool InspectableWebContents::IsGuest() const {
|
||||
return is_guest_;
|
||||
}
|
||||
|
||||
void InspectableWebContents::ReleaseWebContents() {
|
||||
web_contents_.release();
|
||||
WebContentsDestroyed();
|
||||
@@ -479,7 +475,7 @@ void InspectableWebContents::CloseDevTools() {
|
||||
managed_devtools_web_contents_.reset();
|
||||
}
|
||||
embedder_message_dispatcher_.reset();
|
||||
if (!IsGuest())
|
||||
if (!is_guest())
|
||||
web_contents_->Focus();
|
||||
}
|
||||
}
|
||||
@@ -541,10 +537,6 @@ void InspectableWebContents::CallClientFunction(
|
||||
std::move(arguments), std::move(cb));
|
||||
}
|
||||
|
||||
gfx::Rect InspectableWebContents::GetDevToolsBounds() const {
|
||||
return devtools_bounds_;
|
||||
}
|
||||
|
||||
void InspectableWebContents::SaveDevToolsBounds(const gfx::Rect& bounds) {
|
||||
pref_service_->Set(kDevToolsBoundsPref,
|
||||
base::Value{RectToDictionary(bounds)});
|
||||
|
||||
@@ -55,7 +55,7 @@ class InspectableWebContents
|
||||
|
||||
void SetDelegate(InspectableWebContentsDelegate* delegate);
|
||||
InspectableWebContentsDelegate* GetDelegate() const;
|
||||
bool IsGuest() const;
|
||||
[[nodiscard]] bool is_guest() const { return is_guest_; }
|
||||
void ReleaseWebContents();
|
||||
void SetDevToolsWebContents(content::WebContents* devtools);
|
||||
void SetDockState(const std::string& state);
|
||||
@@ -76,7 +76,9 @@ class InspectableWebContents
|
||||
void InspectElement(int x, int y);
|
||||
|
||||
// Return the last position and size of devtools window.
|
||||
gfx::Rect GetDevToolsBounds() const;
|
||||
[[nodiscard]] const gfx::Rect& dev_tools_bounds() const {
|
||||
return devtools_bounds_;
|
||||
}
|
||||
void SaveDevToolsBounds(const gfx::Rect& bounds);
|
||||
|
||||
// Return the last set zoom level of devtools window.
|
||||
|
||||
@@ -121,7 +121,7 @@ void AutofillPopupView::OnSuggestionsChanged() {
|
||||
return;
|
||||
|
||||
CreateChildViews();
|
||||
if (popup_->GetLineCount() == 0) {
|
||||
if (popup_->line_count() == 0) {
|
||||
popup_->Hide();
|
||||
return;
|
||||
}
|
||||
@@ -174,28 +174,28 @@ void AutofillPopupView::DrawAutofillEntry(gfx::Canvas* canvas,
|
||||
|
||||
int x_align_left = value_rect.x();
|
||||
const int value_width = gfx::GetStringWidth(
|
||||
popup_->GetValueAt(index), popup_->GetValueFontListForRow(index));
|
||||
popup_->value_at(index), popup_->GetValueFontListForRow(index));
|
||||
int value_x_align_left = x_align_left;
|
||||
value_x_align_left =
|
||||
is_rtl ? value_rect.right() - value_width : value_rect.x();
|
||||
|
||||
canvas->DrawStringRectWithFlags(
|
||||
popup_->GetValueAt(index), popup_->GetValueFontListForRow(index),
|
||||
popup_->value_at(index), popup_->GetValueFontListForRow(index),
|
||||
GetColorProvider()->GetColor(ui::kColorResultsTableNormalText),
|
||||
gfx::Rect(value_x_align_left, value_rect.y(), value_width,
|
||||
value_rect.height()),
|
||||
text_align);
|
||||
|
||||
// Draw the label text, if one exists.
|
||||
if (!popup_->GetLabelAt(index).empty()) {
|
||||
const int label_width = gfx::GetStringWidth(
|
||||
popup_->GetLabelAt(index), popup_->GetLabelFontListForRow(index));
|
||||
if (auto const& label = popup_->label_at(index); !label.empty()) {
|
||||
const int label_width =
|
||||
gfx::GetStringWidth(label, popup_->GetLabelFontListForRow(index));
|
||||
int label_x_align_left = x_align_left;
|
||||
label_x_align_left =
|
||||
is_rtl ? value_rect.x() : value_rect.right() - label_width;
|
||||
|
||||
canvas->DrawStringRectWithFlags(
|
||||
popup_->GetLabelAt(index), popup_->GetLabelFontListForRow(index),
|
||||
label, popup_->GetLabelFontListForRow(index),
|
||||
GetColorProvider()->GetColor(ui::kColorResultsTableDimmedText),
|
||||
gfx::Rect(label_x_align_left, entry_rect.y(), label_width,
|
||||
entry_rect.height()),
|
||||
@@ -209,8 +209,8 @@ void AutofillPopupView::CreateChildViews() {
|
||||
|
||||
RemoveAllChildViews();
|
||||
|
||||
for (int i = 0; i < popup_->GetLineCount(); ++i) {
|
||||
auto* child_view = new AutofillPopupChildView(popup_->GetValueAt(i));
|
||||
for (int i = 0; i < popup_->line_count(); ++i) {
|
||||
auto* child_view = new AutofillPopupChildView(popup_->value_at(i));
|
||||
child_view->set_drag_controller(this);
|
||||
AddChildView(child_view);
|
||||
}
|
||||
@@ -231,8 +231,7 @@ void AutofillPopupView::DoUpdateBoundsAndRedrawPopup() {
|
||||
}
|
||||
|
||||
void AutofillPopupView::OnPaint(gfx::Canvas* canvas) {
|
||||
if (!popup_ ||
|
||||
static_cast<size_t>(popup_->GetLineCount()) != children().size())
|
||||
if (!popup_ || static_cast<size_t>(popup_->line_count()) != children().size())
|
||||
return;
|
||||
gfx::Canvas* draw_canvas = canvas;
|
||||
SkBitmap bitmap;
|
||||
@@ -249,7 +248,7 @@ void AutofillPopupView::OnPaint(gfx::Canvas* canvas) {
|
||||
GetColorProvider()->GetColor(ui::kColorResultsTableNormalBackground));
|
||||
OnPaintBorder(draw_canvas);
|
||||
|
||||
for (int i = 0; i < popup_->GetLineCount(); ++i) {
|
||||
for (int i = 0; i < popup_->line_count(); ++i) {
|
||||
gfx::Rect line_rect = popup_->GetRowBounds(i);
|
||||
|
||||
DrawAutofillEntry(draw_canvas, i, line_rect);
|
||||
@@ -378,7 +377,7 @@ bool AutofillPopupView::HandleKeyPressEvent(
|
||||
SetSelectedLine(0);
|
||||
return true;
|
||||
case ui::VKEY_NEXT: // Page down.
|
||||
SetSelectedLine(popup_->GetLineCount() - 1);
|
||||
SetSelectedLine(popup_->line_count() - 1);
|
||||
return true;
|
||||
case ui::VKEY_ESCAPE:
|
||||
popup_->Hide();
|
||||
@@ -418,7 +417,7 @@ void AutofillPopupView::AcceptSuggestion(int index) {
|
||||
}
|
||||
|
||||
bool AutofillPopupView::AcceptSelectedLine() {
|
||||
if (!selected_line_ || selected_line_.value() >= popup_->GetLineCount())
|
||||
if (!selected_line_ || selected_line_.value() >= popup_->line_count())
|
||||
return false;
|
||||
|
||||
AcceptSuggestion(selected_line_.value());
|
||||
@@ -438,7 +437,7 @@ void AutofillPopupView::SetSelectedLine(absl::optional<int> selected_line) {
|
||||
return;
|
||||
if (selected_line_ == selected_line)
|
||||
return;
|
||||
if (selected_line && selected_line.value() >= popup_->GetLineCount())
|
||||
if (selected_line && selected_line.value() >= popup_->line_count())
|
||||
return;
|
||||
|
||||
auto previous_selected_line(selected_line_);
|
||||
@@ -458,7 +457,7 @@ void AutofillPopupView::SelectNextLine() {
|
||||
return;
|
||||
|
||||
int new_selected_line = selected_line_ ? *selected_line_ + 1 : 0;
|
||||
if (new_selected_line >= popup_->GetLineCount())
|
||||
if (new_selected_line >= popup_->line_count())
|
||||
new_selected_line = 0;
|
||||
|
||||
SetSelectedLine(new_selected_line);
|
||||
@@ -470,7 +469,7 @@ void AutofillPopupView::SelectPreviousLine() {
|
||||
|
||||
int new_selected_line = selected_line_.value_or(0) - 1;
|
||||
if (new_selected_line < 0)
|
||||
new_selected_line = popup_->GetLineCount() - 1;
|
||||
new_selected_line = popup_->line_count() - 1;
|
||||
|
||||
SetSelectedLine(new_selected_line);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ InspectableWebContentsViewViews::InspectableWebContentsViewViews(
|
||||
: InspectableWebContentsView(inspectable_web_contents),
|
||||
devtools_web_view_(new views::WebView(nullptr)),
|
||||
title_(u"Developer Tools") {
|
||||
if (!inspectable_web_contents_->IsGuest() &&
|
||||
if (!inspectable_web_contents_->is_guest() &&
|
||||
inspectable_web_contents_->GetWebContents()->GetNativeView()) {
|
||||
auto* contents_web_view = new views::WebView(nullptr);
|
||||
contents_web_view->SetWebContents(
|
||||
@@ -116,8 +116,7 @@ void InspectableWebContentsViewViews::ShowDevTools(bool activate) {
|
||||
if (devtools_window_) {
|
||||
devtools_window_web_view_->SetWebContents(
|
||||
inspectable_web_contents_->GetDevToolsWebContents());
|
||||
devtools_window_->SetBounds(
|
||||
inspectable_web_contents()->GetDevToolsBounds());
|
||||
devtools_window_->SetBounds(inspectable_web_contents()->dev_tools_bounds());
|
||||
if (activate) {
|
||||
devtools_window_->Show();
|
||||
} else {
|
||||
@@ -182,7 +181,7 @@ void InspectableWebContentsViewViews::SetIsDocked(bool docked, bool activate) {
|
||||
views::Widget::InitParams params;
|
||||
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
||||
params.delegate = devtools_window_delegate_;
|
||||
params.bounds = inspectable_web_contents()->GetDevToolsBounds();
|
||||
params.bounds = inspectable_web_contents()->dev_tools_bounds();
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
params.wm_role_name = "devtools";
|
||||
|
||||
@@ -296,11 +296,8 @@ void HandleAccessibilityRequestCallback(
|
||||
|
||||
data.Set(kBrowsersField, std::move(window_list));
|
||||
|
||||
std::string json_string;
|
||||
base::JSONWriter::Write(data, &json_string);
|
||||
|
||||
std::move(callback).Run(
|
||||
base::MakeRefCounted<base::RefCountedString>(std::move(json_string)));
|
||||
std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>(
|
||||
base::WriteJson(data).value_or("")));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -120,6 +120,14 @@ void UsbChooserController::GotUsbDeviceList(
|
||||
auto* rfh = content::RenderFrameHost::FromID(render_frame_host_id_);
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
// "select-usb-device" should respect |filters|.
|
||||
devices.erase(std::remove_if(devices.begin(), devices.end(),
|
||||
[this](const auto& device_info) {
|
||||
return !DisplayDevice(*device_info);
|
||||
}),
|
||||
devices.end());
|
||||
|
||||
v8::Local<v8::Object> details = gin::DataObjectBuilder(isolate)
|
||||
.Set("deviceList", devices)
|
||||
.Set("frame", rfh)
|
||||
|
||||
@@ -74,6 +74,7 @@ bool WebContentsZoomController::SetZoomLevel(double level) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
content::NavigationEntry* entry =
|
||||
web_contents()->GetController().GetLastCommittedEntry();
|
||||
|
||||
// Cannot zoom in disabled mode. Also, don't allow changing zoom level on
|
||||
// a crashed tab, an error page or an interstitial page.
|
||||
if (zoom_mode_ == ZOOM_MODE_DISABLED ||
|
||||
@@ -90,7 +91,7 @@ bool WebContentsZoomController::SetZoomLevel(double level) {
|
||||
zoom_level_ = level;
|
||||
|
||||
ZoomChangedEventData zoom_change_data(web_contents(), old_zoom_level,
|
||||
zoom_level_, false /* temporary */,
|
||||
zoom_level_, true /* temporary */,
|
||||
zoom_mode_);
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(zoom_change_data);
|
||||
@@ -154,7 +155,7 @@ void WebContentsZoomController::SetTemporaryZoomLevel(double level) {
|
||||
// Notify observers of zoom level changes.
|
||||
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level_, level,
|
||||
true /* temporary */, zoom_mode_);
|
||||
for (WebContentsZoomObserver& observer : observers_)
|
||||
for (auto& observer : observers_)
|
||||
observer.OnZoomChanged(zoom_change_data);
|
||||
}
|
||||
|
||||
@@ -268,8 +269,10 @@ void WebContentsZoomController::ResetZoomModeOnNavigationIfNeeded(
|
||||
double old_zoom_level = zoom_map->GetZoomLevel(web_contents());
|
||||
double new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme(
|
||||
url.scheme(), net::GetHostOrSpecFromURL(url));
|
||||
|
||||
event_data_ = std::make_unique<ZoomChangedEventData>(
|
||||
web_contents(), old_zoom_level, new_zoom_level, false, ZOOM_MODE_DEFAULT);
|
||||
|
||||
// The call to ClearTemporaryZoomLevel() doesn't generate any events from
|
||||
// HostZoomMap, but the call to UpdateState() at the end of
|
||||
// DidFinishNavigation will notify our observers.
|
||||
@@ -295,11 +298,12 @@ void WebContentsZoomController::DidFinishNavigation(
|
||||
if (!navigation_handle->IsSameDocument()) {
|
||||
ResetZoomModeOnNavigationIfNeeded(navigation_handle->GetURL());
|
||||
SetZoomFactorOnNavigationIfNeeded(navigation_handle->GetURL());
|
||||
|
||||
// If the main frame's content has changed, the new page may have a
|
||||
// different zoom level from the old one.
|
||||
UpdateState(std::string());
|
||||
}
|
||||
|
||||
// If the main frame's content has changed, the new page may have a different
|
||||
// zoom level from the old one.
|
||||
UpdateState(std::string());
|
||||
DCHECK(!event_data_);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ class TrackableObject : public TrackableObjectBase, public EventEmitter<T> {
|
||||
|
||||
// Removes this instance from the weak map.
|
||||
void RemoveFromWeakMap() {
|
||||
if (weak_map_ && weak_map_->Has(weak_map_id()))
|
||||
if (weak_map_)
|
||||
weak_map_->Remove(weak_map_id());
|
||||
}
|
||||
|
||||
|
||||
@@ -9,24 +9,17 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
// Like ES6's WeakMap, but the key is Integer and the value is Weak Pointer.
|
||||
// Like ES6's WeakMap, with a K key and Weak Pointer value.
|
||||
template <typename K>
|
||||
class KeyWeakMap {
|
||||
public:
|
||||
// Records the key and self, used by SetWeak.
|
||||
struct KeyObject {
|
||||
K key;
|
||||
raw_ptr<KeyWeakMap> self;
|
||||
};
|
||||
|
||||
KeyWeakMap() {}
|
||||
virtual ~KeyWeakMap() {
|
||||
~KeyWeakMap() {
|
||||
for (auto& p : map_)
|
||||
p.second.second.ClearWeak();
|
||||
}
|
||||
@@ -45,23 +38,19 @@ class KeyWeakMap {
|
||||
|
||||
// Gets the object from WeakMap by its |key|.
|
||||
v8::MaybeLocal<v8::Object> Get(v8::Isolate* isolate, const K& key) {
|
||||
auto iter = map_.find(key);
|
||||
if (iter == map_.end())
|
||||
return v8::MaybeLocal<v8::Object>();
|
||||
else
|
||||
if (auto iter = map_.find(key); iter != map_.end())
|
||||
return v8::Local<v8::Object>::New(isolate, iter->second.second);
|
||||
return {};
|
||||
}
|
||||
|
||||
// Whether there is an object with |key| in this WeakMap.
|
||||
constexpr bool Has(const K& key) const { return base::Contains(map_, key); }
|
||||
|
||||
// Returns all objects.
|
||||
std::vector<v8::Local<v8::Object>> Values(v8::Isolate* isolate) const {
|
||||
std::vector<v8::Local<v8::Object>> keys;
|
||||
keys.reserve(map_.size());
|
||||
std::vector<v8::Local<v8::Object>> values;
|
||||
values.reserve(map_.size());
|
||||
for (const auto& it : map_)
|
||||
keys.emplace_back(v8::Local<v8::Object>::New(isolate, it.second.second));
|
||||
return keys;
|
||||
values.emplace_back(
|
||||
v8::Local<v8::Object>::New(isolate, it.second.second));
|
||||
return values;
|
||||
}
|
||||
|
||||
// Remove object with |key| in the WeakMap.
|
||||
@@ -75,6 +64,12 @@ class KeyWeakMap {
|
||||
}
|
||||
|
||||
private:
|
||||
// Records the key and self, used by SetWeak.
|
||||
struct KeyObject {
|
||||
K key;
|
||||
raw_ptr<KeyWeakMap> self;
|
||||
};
|
||||
|
||||
static void OnObjectGC(
|
||||
const v8::WeakCallbackInfo<typename KeyWeakMap<K>::KeyObject>& data) {
|
||||
KeyWeakMap<K>::KeyObject* key_object = data.GetParameter();
|
||||
|
||||
@@ -578,8 +578,7 @@ std::shared_ptr<node::Environment> NodeBindings::CreateEnvironment(
|
||||
v8::TryCatch try_catch(isolate);
|
||||
env = node::CreateEnvironment(
|
||||
static_cast<node::IsolateData*>(isolate_data), context, args, exec_args,
|
||||
static_cast<node::EnvironmentFlags::Flags>(flags), {}, {},
|
||||
&OnNodePreload);
|
||||
static_cast<node::EnvironmentFlags::Flags>(flags));
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
std::string err_msg =
|
||||
@@ -695,7 +694,7 @@ std::shared_ptr<node::Environment> NodeBindings::CreateEnvironment(
|
||||
}
|
||||
|
||||
void NodeBindings::LoadEnvironment(node::Environment* env) {
|
||||
node::LoadEnvironment(env, node::StartExecutionCallback{});
|
||||
node::LoadEnvironment(env, node::StartExecutionCallback{}, &OnNodePreload);
|
||||
gin_helper::EmitEvent(env->isolate(), env->process_object(), "loaded");
|
||||
}
|
||||
|
||||
@@ -822,6 +821,10 @@ void OnNodePreload(node::Environment* env,
|
||||
if (dict.Get("versions", &versions)) {
|
||||
versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING);
|
||||
versions.SetReadOnly("chrome", CHROME_VERSION_STRING);
|
||||
#if BUILDFLAG(HAS_VENDOR_VERSION)
|
||||
versions.SetReadOnly(BUILDFLAG(VENDOR_VERSION_NAME),
|
||||
BUILDFLAG(VENDOR_VERSION_VALUE));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Execute lib/node/init.ts.
|
||||
|
||||
@@ -61,6 +61,12 @@ class NodeService : public node::mojom::NodeService {
|
||||
void Initialize(node::mojom::NodeServiceParamsPtr params) override;
|
||||
|
||||
private:
|
||||
// This needs to be initialized first so that it can be destroyed last
|
||||
// after the node::Environment is destroyed. This ensures that if
|
||||
// there are crashes in the node::Environment destructor, they
|
||||
// will be propagated to the exit handler.
|
||||
mojo::Receiver<node::mojom::NodeService> receiver_{this};
|
||||
|
||||
bool node_env_stopped_ = false;
|
||||
|
||||
const std::unique_ptr<NodeBindings> node_bindings_;
|
||||
@@ -73,8 +79,6 @@ class NodeService : public node::mojom::NodeService {
|
||||
|
||||
// depends-on: js_env_'s isolate
|
||||
std::shared_ptr<node::Environment> node_env_;
|
||||
|
||||
mojo::Receiver<node::mojom::NodeService> receiver_{this};
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -25,9 +25,7 @@ describe('setDisplayMediaRequestHandler', () => {
|
||||
// error message:
|
||||
// [ERROR:video_capture_device_client.cc(659)] error@ OnStart@content/browser/media/capture/desktop_capture_device_mac.cc:98, CGDisplayStreamCreate failed, OS message: Value too large to be stored in data type (84)
|
||||
// This is possibly related to the OS/VM setup that CircleCI uses for macOS.
|
||||
// Our arm64 runners are in @jkleinsc's office, and are real machines, so the
|
||||
// test works there.
|
||||
ifit(!(process.platform === 'darwin' && process.arch === 'x64'))('works when calling getDisplayMedia', async function () {
|
||||
ifit(process.platform !== 'darwin')('works when calling getDisplayMedia', async function () {
|
||||
if ((await desktopCapturer.getSources({ types: ['screen'] })).length === 0) {
|
||||
return this.skip();
|
||||
}
|
||||
@@ -306,7 +304,7 @@ describe('setDisplayMediaRequestHandler', () => {
|
||||
expect(ok).to.be.true(message);
|
||||
});
|
||||
|
||||
ifit(!(process.platform === 'darwin' && process.arch === 'x64'))('can supply a screen response to preferCurrentTab', async () => {
|
||||
ifit(process.platform !== 'darwin')('can supply a screen response to preferCurrentTab', async () => {
|
||||
const ses = session.fromPartition('' + Math.random());
|
||||
let requestHandlerCalled = false;
|
||||
ses.setDisplayMediaRequestHandler(async (request, callback) => {
|
||||
|
||||
@@ -2397,18 +2397,18 @@ describe('webContents module', () => {
|
||||
it('emits when moveTo is called', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
w.loadURL('about:blank');
|
||||
w.webContents.executeJavaScript('window.moveTo(100, 100)', true);
|
||||
w.webContents.executeJavaScript('window.moveTo(50, 50)', true);
|
||||
const [, rect] = await once(w.webContents, 'content-bounds-updated') as [any, Electron.Rectangle];
|
||||
const { width, height } = w.getBounds();
|
||||
expect(rect).to.deep.equal({
|
||||
x: 100,
|
||||
y: 100,
|
||||
x: 50,
|
||||
y: 50,
|
||||
width,
|
||||
height
|
||||
});
|
||||
await new Promise(setImmediate);
|
||||
expect(w.getBounds().x).to.equal(100);
|
||||
expect(w.getBounds().y).to.equal(100);
|
||||
expect(w.getBounds().x).to.equal(50);
|
||||
expect(w.getBounds().y).to.equal(50);
|
||||
});
|
||||
|
||||
it('emits when resizeTo is called', async () => {
|
||||
|
||||
31
spec/fixtures/pages/webview-zoom-change-persist-host.html
vendored
Normal file
31
spec/fixtures/pages/webview-zoom-change-persist-host.html
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<html>
|
||||
|
||||
<body>
|
||||
<webview nodeintegration src="app://host1" id="view" partition="webview-temp" />
|
||||
</body>
|
||||
<script>
|
||||
const { ipcRenderer, webFrame } = require('electron')
|
||||
const view = document.getElementById('view')
|
||||
|
||||
let values = {
|
||||
initialZoomLevel: 0,
|
||||
switchZoomLevel: 0,
|
||||
finalZoomLevel: 0,
|
||||
}
|
||||
|
||||
view.addEventListener('dom-ready', async () => {
|
||||
view.setZoomLevel(2.0)
|
||||
values.initialZoomLevel = view.getZoomLevel()
|
||||
|
||||
await view.loadURL('app://host2')
|
||||
view.setZoomLevel(3.0)
|
||||
values.switchZoomLevel = view.getZoomLevel()
|
||||
|
||||
await view.loadURL('app://host1')
|
||||
values.finalZoomLevel = view.getZoomLevel()
|
||||
|
||||
ipcRenderer.send('webview-zoom-persist-level', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
</html>
|
||||
@@ -940,7 +940,13 @@ describe('node feature', () => {
|
||||
});
|
||||
};
|
||||
|
||||
process.once('unhandledRejection', () => done('catch block is delayed to next tick'));
|
||||
let called = false;
|
||||
process.once('unhandledRejection', () => {
|
||||
if (called) return;
|
||||
|
||||
done(new Error('catch block is delayed to next tick'));
|
||||
called = true;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
f3().catch(() => done());
|
||||
|
||||
@@ -352,6 +352,31 @@ describe('<webview> tag', function () {
|
||||
expect(zoomLevel).to.equal(1);
|
||||
});
|
||||
|
||||
it('maintains the zoom level for a given host in the same session after navigation', () => {
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
webviewTag: true,
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
}
|
||||
});
|
||||
|
||||
const zoomPromise = new Promise<void>((resolve) => {
|
||||
ipcMain.on('webview-zoom-persist-level', (_event, values) => {
|
||||
resolve(values);
|
||||
});
|
||||
});
|
||||
|
||||
w.loadFile(path.join(fixtures, 'pages', 'webview-zoom-change-persist-host.html'));
|
||||
|
||||
expect(zoomPromise).to.eventually.deep.equal({
|
||||
initialZoomLevel: 2,
|
||||
switchZoomLevel: 3,
|
||||
finalZoomLevel: 2
|
||||
});
|
||||
});
|
||||
|
||||
it('maintains zoom level on navigation', async () => {
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
|
||||
Reference in New Issue
Block a user