mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a75402ee8 | ||
|
|
b6764c0276 | ||
|
|
1856b71bc1 | ||
|
|
302d4829b4 | ||
|
|
c3c2d844d5 | ||
|
|
28eaf77a25 | ||
|
|
68c436a3e5 | ||
|
|
f659fa4f0b | ||
|
|
1fc49a55d6 | ||
|
|
f46b3f48af | ||
|
|
83a933f303 | ||
|
|
133a69f43e | ||
|
|
6ce4445e63 | ||
|
|
8319490c59 | ||
|
|
5dd4d85b60 | ||
|
|
f09df625f2 | ||
|
|
8d59648128 | ||
|
|
f57244d00d | ||
|
|
f47bc6be2b | ||
|
|
8540d7ddf6 | ||
|
|
dc3a2ffd31 | ||
|
|
351b10d179 | ||
|
|
465e599359 | ||
|
|
b6ad975666 | ||
|
|
38a6fb9a53 | ||
|
|
13fd1105c7 | ||
|
|
5f3eae7119 | ||
|
|
b4613cfe9f | ||
|
|
e95a593199 | ||
|
|
9c2eed2333 | ||
|
|
f6798c5e99 | ||
|
|
e3b8dd1d9d | ||
|
|
2b611690f9 | ||
|
|
f2774427f9 | ||
|
|
16bf1edc77 | ||
|
|
f617308c6f | ||
|
|
acc14843cf | ||
|
|
027d803d73 | ||
|
|
34d77ca691 | ||
|
|
2d0d51ec43 | ||
|
|
ef1243803f | ||
|
|
9629d8fc58 | ||
|
|
744e0ead87 | ||
|
|
be8f54ba8a | ||
|
|
ec0b62ea65 | ||
|
|
e4c86842c3 | ||
|
|
771261f6b7 | ||
|
|
8174553f84 | ||
|
|
35561d7fb0 | ||
|
|
3c9318cc17 | ||
|
|
67a565310a | ||
|
|
e29c6aef2c | ||
|
|
d4edab2c9f | ||
|
|
0e0bf5495b | ||
|
|
bb7de2d7a0 | ||
|
|
2dc9091b3e | ||
|
|
9af52185e1 | ||
|
|
52c878b6bc | ||
|
|
7cdf38c3fc | ||
|
|
7a1c596d63 | ||
|
|
c7a7e0f56b | ||
|
|
b0d4474536 | ||
|
|
8ae3f8bf55 | ||
|
|
24e385f54b | ||
|
|
91b8fa26b8 | ||
|
|
105ab32645 | ||
|
|
8e5e91cfc1 | ||
|
|
582eb5c9bd | ||
|
|
8fe397cecc | ||
|
|
972213b032 | ||
|
|
5e36eed062 |
2416
.circleci/build_config.yml
Normal file
2416
.circleci/build_config.yml
Normal file
File diff suppressed because it is too large
Load Diff
2622
.circleci/config.yml
2622
.circleci/config.yml
File diff suppressed because it is too large
Load Diff
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -4,7 +4,7 @@
|
||||
# https://git-scm.com/docs/gitignore
|
||||
|
||||
# Upgrades WG
|
||||
/patches/ @electron/wg-upgrades
|
||||
/patches/ @electron/wg-upgrades @electron/wg-security
|
||||
DEPS @electron/wg-upgrades
|
||||
|
||||
# Releases WG
|
||||
|
||||
@@ -1 +1 @@
|
||||
14.2.2
|
||||
14.2.7
|
||||
@@ -731,6 +731,8 @@ first available device will be selected. `callback` should be called with
|
||||
`deviceId` to be selected, passing empty string to `callback` will
|
||||
cancel the request.
|
||||
|
||||
If no event listener is added for this event, all bluetooth requests will be cancelled.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
@@ -1595,7 +1597,7 @@ app.whenReady().then(() => {
|
||||
|
||||
* `options` Object (optional)
|
||||
* `mode` String - Opens the devtools with specified dock state, can be
|
||||
`right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
`left`, `right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
In `undocked` mode it's possible to dock back. In `detach` mode it's not.
|
||||
* `activate` Boolean (optional) - Whether to bring the opened devtools window
|
||||
to the foreground. The default is `true`.
|
||||
|
||||
@@ -65,6 +65,9 @@ window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIn
|
||||
`features` will be passed to any registered `webContents`'s
|
||||
`did-create-window` event handler in the `options` argument.
|
||||
* `frameName` follows the specification of `windowName` located in the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters).
|
||||
* When opening `about:blank`, the child window's `WebPreferences` will be copied
|
||||
from the parent window, and there is no way to override it because Chromium
|
||||
skips browser side navigation in this case.
|
||||
|
||||
To customize or cancel the creation of the window, you can optionally set an
|
||||
override handler with `webContents.setWindowOpenHandler()` from the main
|
||||
|
||||
@@ -43,8 +43,9 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
|
||||
|
||||
## Using the symbol server in Visual Studio
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
## Troubleshooting: Symbols will not load
|
||||
|
||||
|
||||
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/images/vs-tools-options.png
Normal file
BIN
docs/images/vs-tools-options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -669,16 +669,6 @@ WebContents.prototype._init = function () {
|
||||
postBody
|
||||
};
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
|
||||
// if attempting to use this API with the deprecated new-window event,
|
||||
// windowOpenOverriddenOptions will always return null. This ensures
|
||||
// short-term backwards compatibility until new-window is removed.
|
||||
const parsedFeatures = parseFeatures(rawFeatures);
|
||||
const overriddenFeatures: BrowserWindowConstructorOptions = {
|
||||
...parsedFeatures.options,
|
||||
webPreferences: parsedFeatures.webPreferences
|
||||
};
|
||||
windowOpenOverriddenOptions = windowOpenOverriddenOptions || overriddenFeatures;
|
||||
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
@@ -688,9 +678,19 @@ WebContents.prototype._init = function () {
|
||||
transparent: windowOpenOverriddenOptions.transparent,
|
||||
...windowOpenOverriddenOptions.webPreferences
|
||||
} : undefined;
|
||||
this._setNextChildWebPreferences(
|
||||
makeWebPreferences({ embedder: event.sender, secureOverrideWebPreferences })
|
||||
);
|
||||
// TODO(zcbenz): The features string is parsed twice: here where it is
|
||||
// passed to C++, and in |makeBrowserWindowOptions| later where it is
|
||||
// not actually used since the WebContents is created here.
|
||||
// We should be able to remove the latter once the |nativeWindowOpen|
|
||||
// option is removed.
|
||||
const { webPreferences: parsedWebPreferences } = parseFeatures(rawFeatures);
|
||||
// Parameters should keep same with |makeBrowserWindowOptions|.
|
||||
const webPreferences = makeWebPreferences({
|
||||
embedder: event.sender,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
secureOverrideWebPreferences
|
||||
});
|
||||
this._setNextChildWebPreferences(webPreferences);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -738,6 +738,14 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
this.on('select-bluetooth-device', (event, devices, callback) => {
|
||||
if (this.listenerCount('select-bluetooth-device') === 1) {
|
||||
// Cancel it if there are no handlers
|
||||
event.preventDefault();
|
||||
callback('');
|
||||
}
|
||||
});
|
||||
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
|
||||
|
||||
@@ -217,6 +217,10 @@ function makeBrowserWindowOptions ({ embedder, features, overrideOptions }: {
|
||||
height: 600,
|
||||
...parsedOptions,
|
||||
...overrideOptions,
|
||||
// Note that for |nativeWindowOpen: true| the WebContents is created in
|
||||
// |api::WebContents::WebContentsCreatedWithFullParams|, with prefs
|
||||
// parsed in the |-will-add-new-contents| event.
|
||||
// The |webPreferences| here is only used by |nativeWindowOpen: false|.
|
||||
webPreferences: makeWebPreferences({
|
||||
embedder,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "14.2.2",
|
||||
"version": "14.2.7",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -33,7 +33,7 @@
|
||||
"asar": "^3.0.3",
|
||||
"aws-sdk": "^2.727.1",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.4.0",
|
||||
"colors": "1.4.0",
|
||||
"dotenv-safe": "^4.0.4",
|
||||
"dugite": "^1.45.0",
|
||||
"eslint": "^7.4.0",
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
fix_integer_overflow_in_blocklayoutencoder.patch
|
||||
cherry-pick-bdffa0ea5148.patch
|
||||
cherry-pick-05e69c75905f.patch
|
||||
cherry-pick-891020ed64d4.patch
|
||||
cherry-pick-2b98abd8cb6c.patch
|
||||
cherry-pick-cc44ae61f37b.patch
|
||||
m98_vulkan_fix_vkcmdresolveimage_extents.patch
|
||||
m98_vulkan_fix_vkcmdresolveimage_offsets.patch
|
||||
cherry-pick-49e8ff16f1fe.patch
|
||||
|
||||
118
patches/angle/cherry-pick-05e69c75905f.patch
Normal file
118
patches/angle/cherry-pick-05e69c75905f.patch
Normal file
@@ -0,0 +1,118 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lingfeng Yang <lfy@google.com>
|
||||
Date: Wed, 1 Dec 2021 18:16:14 -0800
|
||||
Subject: M96: Vulkan: remove staged updates on storage set
|
||||
|
||||
Previously we would allow staged updates to bigger versions of a texture
|
||||
to go through even if the texture was redefined via glTexStorage*.
|
||||
|
||||
Bug: chromium:1262080
|
||||
Change-Id: I9d861fed68d4a1fdcd0777b97caf729cc74c595e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3312718
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Lingfeng Yang <lfy@google.com>
|
||||
(cherry picked from commit 929c8ed4e8c3912cf027d843e7a2af47b21e5612)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3328001
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index 68e7ffa73781b8431188d53c97d388bd1c7ffb52..ee159cbd3621a655f00ccf2eb24c8711e050da8b 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -1236,6 +1236,10 @@ angle::Result TextureVk::setStorageMultisample(const gl::Context *context,
|
||||
{
|
||||
releaseAndDeleteImageAndViews(contextVk);
|
||||
}
|
||||
+ else if (mImage)
|
||||
+ {
|
||||
+ mImage->releaseStagingBuffer(contextVk->getRenderer());
|
||||
+ }
|
||||
|
||||
const vk::Format &format = renderer->getFormat(internalformat);
|
||||
ANGLE_TRY(ensureImageAllocated(contextVk, format));
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index f0b48cb803981d1fdc7c30093c7bf7c0d170dece..9a20527ae5b8aa33ad2fcb9572eb2180710cd31c 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -9547,6 +9547,73 @@ void main()
|
||||
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
|
||||
}
|
||||
|
||||
+class TextureChangeStorageUploadTest : public ANGLETest
|
||||
+{
|
||||
+ protected:
|
||||
+ TextureChangeStorageUploadTest()
|
||||
+ {
|
||||
+ setWindowWidth(256);
|
||||
+ setWindowHeight(256);
|
||||
+ setConfigRedBits(8);
|
||||
+ setConfigGreenBits(8);
|
||||
+ setConfigBlueBits(8);
|
||||
+ setConfigAlphaBits(8);
|
||||
+ }
|
||||
+
|
||||
+ void testSetUp() override
|
||||
+ {
|
||||
+ mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ if (mProgram == 0)
|
||||
+ {
|
||||
+ FAIL() << "shader compilation failed.";
|
||||
+ }
|
||||
+
|
||||
+ mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+
|
||||
+ glClearColor(0, 0, 0, 0);
|
||||
+ glClearDepthf(0.0);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
+
|
||||
+ glEnable(GL_BLEND);
|
||||
+ glDisable(GL_DEPTH_TEST);
|
||||
+
|
||||
+ glGenTextures(1, &mTexture);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ }
|
||||
+
|
||||
+ void testTearDown() override
|
||||
+ {
|
||||
+ glDeleteTextures(1, &mTexture);
|
||||
+ glDeleteProgram(mProgram);
|
||||
+ }
|
||||
+
|
||||
+ GLuint mProgram;
|
||||
+ GLint mColorLocation;
|
||||
+ GLuint mTexture;
|
||||
+};
|
||||
+
|
||||
+// Verify that respecifying storage and re-uploading doesn't crash.
|
||||
+TEST_P(TextureChangeStorageUploadTest, Basic)
|
||||
+{
|
||||
+ constexpr int kImageSize = 8; // 4 doesn't trip ASAN
|
||||
+ constexpr int kSmallerImageSize = kImageSize / 2;
|
||||
+ EXPECT_GT(kImageSize, kSmallerImageSize);
|
||||
+ EXPECT_GT(kSmallerImageSize / 2, 0);
|
||||
+
|
||||
+ std::array<GLColor, kImageSize * kImageSize> kColor;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ kColor.data());
|
||||
+ glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
|
||||
+ // need partial update to sidestep optimizations that remove the full upload
|
||||
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
|
||||
+ GL_UNSIGNED_BYTE, kColor.data());
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
#define ES2_EMULATE_COPY_TEX_IMAGE() \
|
||||
@@ -9660,4 +9727,6 @@ ANGLE_INSTANTIATE_TEST_ES31_AND(TextureBufferTestES31, WithDirectSPIRVGeneration
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
|
||||
ANGLE_INSTANTIATE_TEST_ES31_AND(CopyImageTestES31, WithDirectSPIRVGeneration(ES31_VULKAN()));
|
||||
|
||||
+ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
|
||||
+
|
||||
} // anonymous namespace
|
||||
96
patches/angle/cherry-pick-2b98abd8cb6c.patch
Normal file
96
patches/angle/cherry-pick-2b98abd8cb6c.patch
Normal file
@@ -0,0 +1,96 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Tue, 30 Nov 2021 23:48:30 -0500
|
||||
Subject: M96: Vulkan: Fix image respecify's usage tracking
|
||||
|
||||
When respecifying an image due to mip level count changes, the previous
|
||||
image is staged as an update to the new image. The resource usage info
|
||||
was not being transferred to the image being staged as an update,
|
||||
causing it to be prematurely deleted.
|
||||
|
||||
Test based on one authored by sugoi@google.com.
|
||||
|
||||
Bug: chromium:1270658
|
||||
Bug: angleproject:4835
|
||||
Change-Id: I9810f8940e0107bc8a04fa3fb9c26a045c0d689c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3318257
|
||||
Reviewed-by: Lingfeng Yang <lfy@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.cpp b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
index efb04acf0fe5dc7c2d860ac8cc33dbe30691c4a3..e2cd1e3a96b1fa4e034efe6ed78ea1a787af6af6 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
@@ -26,6 +26,12 @@ Resource::Resource(Resource &&other) : Resource()
|
||||
mUse = std::move(other.mUse);
|
||||
}
|
||||
|
||||
+Resource &Resource::operator=(Resource &&rhs)
|
||||
+{
|
||||
+ std::swap(mUse, rhs.mUse);
|
||||
+ return *this;
|
||||
+}
|
||||
+
|
||||
Resource::~Resource()
|
||||
{
|
||||
mUse.release();
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.h b/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
index 67440122bf7fa0f72b5412816853b2eddd770fd4..abab9900b7361c8564cb1ad30e0841eaf873ee2e 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
@@ -192,6 +192,7 @@ class Resource : angle::NonCopyable
|
||||
protected:
|
||||
Resource();
|
||||
Resource(Resource &&other);
|
||||
+ Resource &operator=(Resource &&rhs);
|
||||
|
||||
// Current resource lifetime.
|
||||
SharedResourceUse mUse;
|
||||
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
index e8378d01aa29b98ea4b6a9db270c41b19ba1809a..0c21d3ea8b075cbd0fbbe95d8f4754647276c21f 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
@@ -6020,6 +6020,9 @@ void ImageHelper::stageSelfAsSubresourceUpdates(ContextVk *contextVk,
|
||||
// Move the necessary information for staged update to work, and keep the rest as part of this
|
||||
// object.
|
||||
|
||||
+ // Usage info
|
||||
+ prevImage->get().Resource::operator=(std::move(*this));
|
||||
+
|
||||
// Vulkan objects
|
||||
prevImage->get().mImage = std::move(mImage);
|
||||
prevImage->get().mDeviceMemory = std::move(mDeviceMemory);
|
||||
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
|
||||
index 4db00e78a7d2f7375fdcb9228fbdc83395973125..8a6d01ca36a84a9e294de3f6f0114ee7a54e1d9a 100644
|
||||
--- a/src/tests/gl_tests/MipmapTest.cpp
|
||||
+++ b/src/tests/gl_tests/MipmapTest.cpp
|
||||
@@ -2106,6 +2106,30 @@ TEST_P(MipmapTestES3, GenerateMipmapZeroSize)
|
||||
glGenerateMipmap(GL_TEXTURE_3D);
|
||||
}
|
||||
|
||||
+// Test that reducing the size of the mipchain by resizing the base image then deleting it doesn't
|
||||
+// cause a crash. Issue found by fuzzer.
|
||||
+TEST_P(MipmapTestES3, ResizeBaseMipTo1x1ThenDelete)
|
||||
+{
|
||||
+ GLTexture tex;
|
||||
+ glBindTexture(GL_TEXTURE_2D, tex);
|
||||
+
|
||||
+ std::vector<GLColor> data(2, GLColor::blue);
|
||||
+
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+
|
||||
+ clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
|
||||
+
|
||||
+ data[0] = GLColor::green;
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+
|
||||
+ clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
|
||||
+
|
||||
+ tex.reset();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MipmapTest);
|
||||
381
patches/angle/cherry-pick-49e8ff16f1fe.patch
Normal file
381
patches/angle/cherry-pick-49e8ff16f1fe.patch
Normal file
@@ -0,0 +1,381 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Tue, 25 Jan 2022 12:15:16 -0500
|
||||
Subject: M99: Vulkan: Fix texture array level redefinition
|
||||
|
||||
When a level of a texture is redefined, all staged updates to that level
|
||||
should be removed, not the ones specific to the new layers. The bug
|
||||
fixed was that if the texture was redefined to have its number of layers
|
||||
changed, the staged higher-layer-count update to the image was not
|
||||
removed.
|
||||
|
||||
Bug: chromium:1289383
|
||||
Change-Id: Iab79c38d846d1abbdd92e11b1b60a3adf0fbde4c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3441309
|
||||
Reviewed-by: Lingfeng Yang <lfy@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index ee159cbd3621a655f00ccf2eb24c8711e050da8b..859e017d491f49d76db8c5fdd4c76ff51759075c 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -1553,12 +1553,25 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context,
|
||||
|
||||
if (mImage != nullptr)
|
||||
{
|
||||
- // If there is any staged changes for this index, we can remove them since we're going to
|
||||
+ // If there are any staged changes for this index, we can remove them since we're going to
|
||||
// override them with this call.
|
||||
gl::LevelIndex levelIndexGL(index.getLevelIndex());
|
||||
uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
|
||||
- mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
|
||||
- index.getLayerCount());
|
||||
+ if (gl::IsArrayTextureType(index.getType()))
|
||||
+ {
|
||||
+ // A multi-layer texture is being redefined, remove all updates to this level; the
|
||||
+ // number of layers may have changed.
|
||||
+ mImage->removeStagedUpdates(contextVk, levelIndexGL, levelIndexGL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ // Otherwise remove only updates to this layer. For example, cube map updates can be
|
||||
+ // done through glTexImage2D, one per cube face (i.e. layer) and so should not remove
|
||||
+ // updates to the other layers.
|
||||
+ ASSERT(index.getLayerCount() == 1);
|
||||
+ mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
|
||||
+ index.getLayerCount());
|
||||
+ }
|
||||
|
||||
if (mImage->valid())
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
|
||||
index 8a6d01ca36a84a9e294de3f6f0114ee7a54e1d9a..957a52304edc9aa245f9f21e5557cc105cbad789 100644
|
||||
--- a/src/tests/gl_tests/MipmapTest.cpp
|
||||
+++ b/src/tests/gl_tests/MipmapTest.cpp
|
||||
@@ -1686,6 +1686,106 @@ TEST_P(MipmapTestES3, MipmapsForTexture3D)
|
||||
EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
}
|
||||
|
||||
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
|
||||
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(MipmapTestES3, TextureArrayRedefineThenGenerateMipmap)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red, then redefine it and fill with green
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Generate mipmaps
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mArrayProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
|
||||
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(MipmapTestES3, TextureArrayUseThenRedefineThenGenerateMipmap)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red.
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Generate mipmap
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mArrayProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Draw the fourth slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Redefine the image and fill with green
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ // Generate mipmap
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Create a 2D texture with levels 0-2, call GenerateMipmap with base level 1 so that level 0 stays
|
||||
// the same, and then sample levels 0 and 2.
|
||||
// GLES 3.0.4 section 3.8.10:
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index f1df6b5b947ca2684a9db7bd800f5de59ce0c64c..54ab7910ddeacf740a27816c6b9c5a9ce12cba68 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -1025,31 +1025,37 @@ class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
|
||||
class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
{
|
||||
protected:
|
||||
- Texture2DArrayTestES3() : TexCoordDrawTest(), m2DArrayTexture(0), mTextureArrayLocation(-1) {}
|
||||
+ Texture2DArrayTestES3()
|
||||
+ : TexCoordDrawTest(),
|
||||
+ m2DArrayTexture(0),
|
||||
+ mTextureArrayLocation(-1),
|
||||
+ mTextureArraySliceUniformLocation(-1)
|
||||
+ {}
|
||||
|
||||
const char *getVertexShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "out vec2 texcoord;\n"
|
||||
- "in vec4 position;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
|
||||
- " texcoord = (position.xy * 0.5) + 0.5;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+out vec2 texcoord;
|
||||
+in vec4 position;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(position.xy, 0.0, 1.0);
|
||||
+ texcoord = (position.xy * 0.5) + 0.5;
|
||||
+})";
|
||||
}
|
||||
|
||||
const char *getFragmentShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "precision highp float;\n"
|
||||
- "uniform highp sampler2DArray tex2DArray;\n"
|
||||
- "in vec2 texcoord;\n"
|
||||
- "out vec4 fragColor;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+precision highp float;
|
||||
+uniform highp sampler2DArray tex2DArray;
|
||||
+uniform int slice;
|
||||
+in vec2 texcoord;
|
||||
+out vec4 fragColor;
|
||||
+void main()
|
||||
+{
|
||||
+ fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
|
||||
+})";
|
||||
}
|
||||
|
||||
void testSetUp() override
|
||||
@@ -1061,6 +1067,9 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
|
||||
ASSERT_NE(-1, mTextureArrayLocation);
|
||||
|
||||
+ mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
|
||||
+ ASSERT_NE(-1, mTextureArraySliceUniformLocation);
|
||||
+
|
||||
glGenTextures(1, &m2DArrayTexture);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
@@ -1073,6 +1082,7 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
|
||||
GLuint m2DArrayTexture;
|
||||
GLint mTextureArrayLocation;
|
||||
+ GLint mTextureArraySliceUniformLocation;
|
||||
};
|
||||
|
||||
class TextureSizeTextureArrayTest : public TexCoordDrawTest
|
||||
@@ -1715,28 +1725,28 @@ class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
|
||||
|
||||
const char *getVertexShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "out vec2 texcoord;\n"
|
||||
- "in vec4 position;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
|
||||
- " texcoord = (position.xy * 0.5) + 0.5;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+out vec2 texcoord;
|
||||
+in vec4 position;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(position.xy, 0.0, 1.0);
|
||||
+ texcoord = (position.xy * 0.5) + 0.5;
|
||||
+})";
|
||||
}
|
||||
|
||||
const char *getFragmentShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "precision highp float;\n"
|
||||
- "uniform highp usampler2DArray tex2DArray;\n"
|
||||
- "in vec2 texcoord;\n"
|
||||
- "out vec4 fragColor;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " fragColor = vec4(texture(tex2DArray, vec3(texcoord.x, texcoord.y, "
|
||||
- "0.0)))/255.0;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+precision highp float;
|
||||
+uniform highp usampler2DArray tex2DArray;
|
||||
+uniform int slice;
|
||||
+in vec2 texcoord;
|
||||
+out vec4 fragColor;
|
||||
+void main()
|
||||
+{
|
||||
+ fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
|
||||
+})";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4972,6 +4982,94 @@ TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensio
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
|
||||
}
|
||||
|
||||
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
|
||||
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red, then redefine it and fill with green
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
|
||||
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red.
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Draw the fourth slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Redefine the image and fill with green
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Test that texture completeness is updated if texture max level changes.
|
||||
// GLES 3.0.4 section 3.8.13 Texture completeness
|
||||
TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
|
||||
163
patches/angle/cherry-pick-891020ed64d4.patch
Normal file
163
patches/angle/cherry-pick-891020ed64d4.patch
Normal file
@@ -0,0 +1,163 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Date: Mon, 22 Nov 2021 14:30:52 -0500
|
||||
Subject: Ignore the pixel unpack state for compressed textures.
|
||||
|
||||
From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding
|
||||
a compressed texture image
|
||||
This was causing a bad access when calling compressedTexImage3D
|
||||
with GL_UNPACK_IMAGE_HEIGHT greater than the image height.
|
||||
|
||||
Bug: chromium:1267496
|
||||
Change-Id: I9b1f4c645548af64f2695fd23262225a1ad07cd7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3296622
|
||||
Commit-Queue: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 870f458f507ff7ba0f67b28a30a27955ce79dd3e)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3309097
|
||||
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
|
||||
index 1e989ebaffb25da1a1a281afa0610a9088232119..67356b5bd47e96e98e2a5e4880a71f5042ca918d 100644
|
||||
--- a/src/libANGLE/Context.cpp
|
||||
+++ b/src/libANGLE/Context.cpp
|
||||
@@ -4923,7 +4923,9 @@ void Context::compressedTexImage2D(TextureTarget target,
|
||||
|
||||
Extents size(width, height, 1);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, mState.getUnpackState(), target, level,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
|
||||
internalformat, size, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
@@ -4955,7 +4957,9 @@ void Context::compressedTexImage3D(TextureTarget target,
|
||||
|
||||
Extents size(width, height, depth);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, mState.getUnpackState(), target, level,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
|
||||
internalformat, size, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
@@ -4989,8 +4993,10 @@ void Context::compressedTexSubImage2D(TextureTarget target,
|
||||
|
||||
Box area(xoffset, yoffset, 0, width, height, 1);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, mState.getUnpackState(), target, level,
|
||||
- area, format, imageSize,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
|
||||
+ format, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
|
||||
@@ -5031,8 +5037,10 @@ void Context::compressedTexSubImage3D(TextureTarget target,
|
||||
|
||||
Box area(xoffset, yoffset, zoffset, width, height, depth);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, mState.getUnpackState(), target, level,
|
||||
- area, format, imageSize,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
|
||||
+ format, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index 9a20527ae5b8aa33ad2fcb9572eb2180710cd31c..f1df6b5b947ca2684a9db7bd800f5de59ce0c64c 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -5011,6 +5011,43 @@ TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
|
||||
}
|
||||
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture3DTestES3, PixelUnpackStateTexImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
|
||||
+
|
||||
+ uint8_t data[64] = {0};
|
||||
+ glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
|
||||
+
|
||||
+ uint8_t data[64] = {0};
|
||||
+ glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
|
||||
+
|
||||
+ glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4,
|
||||
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Test that 3D texture completeness is updated if texture max level changes.
|
||||
// GLES 3.0.4 section 3.8.13 Texture completeness
|
||||
TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
|
||||
@@ -5690,6 +5727,41 @@ TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
|
||||
EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
|
||||
}
|
||||
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture2DTestES3, PixelUnpackStateTexImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 5);
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture2D);
|
||||
+
|
||||
+ uint8_t data[16] = {0};
|
||||
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 0, 16, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture2D);
|
||||
+
|
||||
+ uint8_t data[16] = {0};
|
||||
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 0, 16, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 5);
|
||||
+
|
||||
+ glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Copied from Texture2DTest::TexStorage
|
||||
// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
|
||||
// default color.
|
||||
169
patches/angle/cherry-pick-bdffa0ea5148.patch
Normal file
169
patches/angle/cherry-pick-bdffa0ea5148.patch
Normal file
@@ -0,0 +1,169 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Thu, 2 Dec 2021 14:30:42 -0500
|
||||
Subject: M96: Fix changing attached renderbuffer from MSRTT to non-MSRTT
|
||||
|
||||
FramebufferAttachment::mRenderToTextureSamples was never updated if the
|
||||
renderbuffer storage was changed after attaching to framebuffer.
|
||||
|
||||
Bug: chromium:1272068
|
||||
Change-Id: Icddbb5650354ea16d06c49532d6a8d0ae962ab5f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3320923
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp
|
||||
index 00714d0a0303050893abcd9564e760b22d9b2de5..720d3000d42e6c8c23214e66eee4aa6982216a60 100644
|
||||
--- a/src/libANGLE/FramebufferAttachment.cpp
|
||||
+++ b/src/libANGLE/FramebufferAttachment.cpp
|
||||
@@ -129,7 +129,7 @@ void FramebufferAttachment::attach(const Context *context,
|
||||
mNumViews = numViews;
|
||||
mBaseViewIndex = baseViewIndex;
|
||||
mIsMultiview = isMultiview;
|
||||
- mRenderToTextureSamples = samples;
|
||||
+ mRenderToTextureSamples = type == GL_RENDERBUFFER ? kDefaultRenderToTextureSamples : samples;
|
||||
resource->onAttach(context, framebufferSerial);
|
||||
|
||||
if (mResource != nullptr)
|
||||
@@ -222,6 +222,29 @@ GLint FramebufferAttachment::getBaseViewIndex() const
|
||||
return mBaseViewIndex;
|
||||
}
|
||||
|
||||
+bool FramebufferAttachment::isRenderToTexture() const
|
||||
+{
|
||||
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
|
||||
+
|
||||
+ if (mType == GL_RENDERBUFFER)
|
||||
+ {
|
||||
+ return getRenderbuffer()->getMultisamplingMode() ==
|
||||
+ MultisamplingMode::MultisampledRenderToTexture;
|
||||
+ }
|
||||
+ return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
|
||||
+}
|
||||
+
|
||||
+GLsizei FramebufferAttachment::getRenderToTextureSamples() const
|
||||
+{
|
||||
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
|
||||
+
|
||||
+ if (mType == GL_RENDERBUFFER)
|
||||
+ {
|
||||
+ return getRenderbuffer()->getState().getSamples();
|
||||
+ }
|
||||
+ return mRenderToTextureSamples;
|
||||
+}
|
||||
+
|
||||
Texture *FramebufferAttachment::getTexture() const
|
||||
{
|
||||
return rx::GetAs<Texture>(mResource);
|
||||
diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h
|
||||
index 013a1e02874e4df3680e9b4a56f74aaf94d188a9..6235b42cf2fdfcb0e9fa33242b458934f1afa5b0 100644
|
||||
--- a/src/libANGLE/FramebufferAttachment.h
|
||||
+++ b/src/libANGLE/FramebufferAttachment.h
|
||||
@@ -117,11 +117,8 @@ class FramebufferAttachment final
|
||||
bool isMultiview() const;
|
||||
GLint getBaseViewIndex() const;
|
||||
|
||||
- bool isRenderToTexture() const
|
||||
- {
|
||||
- return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
|
||||
- }
|
||||
- GLsizei getRenderToTextureSamples() const { return mRenderToTextureSamples; }
|
||||
+ bool isRenderToTexture() const;
|
||||
+ GLsizei getRenderToTextureSamples() const;
|
||||
|
||||
// The size of the underlying resource the attachment points to. The 'depth' value will
|
||||
// correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
|
||||
@@ -195,6 +192,14 @@ class FramebufferAttachment final
|
||||
GLsizei mNumViews;
|
||||
bool mIsMultiview;
|
||||
GLint mBaseViewIndex;
|
||||
+ // A single-sampled texture can be attached to a framebuffer either as single-sampled or as
|
||||
+ // multisampled-render-to-texture. In the latter case, |mRenderToTextureSamples| will contain
|
||||
+ // the number of samples. For renderbuffers, the number of samples is inherited from the
|
||||
+ // renderbuffer itself.
|
||||
+ //
|
||||
+ // Note that textures cannot change storage between single and multisample once attached to a
|
||||
+ // framebuffer. Renderbuffers instead can, and caching the number of renderbuffer samples here
|
||||
+ // can lead to stale data.
|
||||
GLsizei mRenderToTextureSamples;
|
||||
};
|
||||
|
||||
@@ -253,8 +258,7 @@ inline Format FramebufferAttachment::getFormat() const
|
||||
|
||||
inline GLsizei FramebufferAttachment::getSamples() const
|
||||
{
|
||||
- return (mRenderToTextureSamples != kDefaultRenderToTextureSamples) ? getRenderToTextureSamples()
|
||||
- : getResourceSamples();
|
||||
+ return isRenderToTexture() ? getRenderToTextureSamples() : getResourceSamples();
|
||||
}
|
||||
|
||||
inline GLsizei FramebufferAttachment::getResourceSamples() const
|
||||
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
index ff01848daff091d92e4fdce08bc6842a3bdd3ee9..cd733be3ae5c179860d882e305ec84d093a283ed 100644
|
||||
--- a/src/tests/gl_tests/FramebufferTest.cpp
|
||||
+++ b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
@@ -3366,6 +3366,65 @@ void main() {
|
||||
|
||||
// This shouldn't crash.
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Modify renderbuffer attachment samples after bind
|
||||
+TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySamples)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ glUseProgram(program);
|
||||
+ GLint colorUniformLocation =
|
||||
+ glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
|
||||
+ ASSERT_NE(colorUniformLocation, -1);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+
|
||||
+ GLsizei size = 16;
|
||||
+ glViewport(0, 0, size, size);
|
||||
+
|
||||
+ GLRenderbuffer color;
|
||||
+ glBindRenderbuffer(GL_RENDERBUFFER, color);
|
||||
+
|
||||
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, size, size);
|
||||
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
|
||||
+
|
||||
+ glUniform4f(colorUniformLocation, 1, 0, 0, 1);
|
||||
+ drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Modify renderbuffer attachment size after bind
|
||||
+TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ glUseProgram(program);
|
||||
+ GLint colorUniformLocation =
|
||||
+ glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
|
||||
+ ASSERT_NE(colorUniformLocation, -1);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+
|
||||
+ GLsizei size = 16;
|
||||
+ glViewport(0, 0, size, size);
|
||||
+
|
||||
+ GLRenderbuffer color;
|
||||
+ glBindRenderbuffer(GL_RENDERBUFFER, color);
|
||||
+
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
|
||||
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size / 2, size * 2);
|
||||
+
|
||||
+ glUniform4f(colorUniformLocation, 1, 0, 0, 1);
|
||||
+ drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
ANGLE_INSTANTIATE_TEST_ES2(AddMockTextureNoRenderTargetTest);
|
||||
43
patches/angle/cherry-pick-cc44ae61f37b.patch
Normal file
43
patches/angle/cherry-pick-cc44ae61f37b.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 4 Jan 2022 12:28:55 -0500
|
||||
Subject: M96: D3D11: Fix OOB access in vertex conversion code.
|
||||
|
||||
This could happen when using certain combinations of stride and
|
||||
offset. Fix the issue by using checked math.
|
||||
|
||||
Bug: chromium:1274499
|
||||
Change-Id: I3e286a30fe128ab4684ee5e172dc9e3345e3b2f4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3365657
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
index 43fcdc8de5a0d15aacf4b06e0e32df008d78f886..031a12e2b8b0e0dee91087c02cbd2f8b17435a2b 100644
|
||||
--- a/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
@@ -58,17 +58,15 @@ int ElementsInBuffer(const gl::VertexAttribute &attrib,
|
||||
const gl::VertexBinding &binding,
|
||||
unsigned int size)
|
||||
{
|
||||
- // Size cannot be larger than a GLsizei
|
||||
- if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
|
||||
- {
|
||||
- size = static_cast<unsigned int>(std::numeric_limits<int>::max());
|
||||
- }
|
||||
+ angle::CheckedNumeric<size_t> bufferSize(size);
|
||||
+ angle::CheckedNumeric<size_t> stride = ComputeVertexAttributeStride(attrib, binding);
|
||||
+ angle::CheckedNumeric<size_t> offset = ComputeVertexAttributeOffset(attrib, binding);
|
||||
+ angle::CheckedNumeric<size_t> elementSize = ComputeVertexAttributeTypeSize(attrib);
|
||||
+
|
||||
+ auto elementsInBuffer = (bufferSize - (offset % stride) + (stride - elementSize)) / stride;
|
||||
+ auto elementsInBufferInt = angle::CheckedNumeric<int>::cast(elementsInBuffer);
|
||||
|
||||
- GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib, binding));
|
||||
- GLsizei offset = static_cast<GLsizei>(ComputeVertexAttributeOffset(attrib, binding));
|
||||
- return (size - offset % stride +
|
||||
- (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
|
||||
- stride;
|
||||
+ return elementsInBufferInt.ValueOrDefault(0);
|
||||
}
|
||||
|
||||
// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
|
||||
112
patches/angle/m98_vulkan_fix_vkcmdresolveimage_extents.patch
Normal file
112
patches/angle/m98_vulkan_fix_vkcmdresolveimage_extents.patch
Normal file
@@ -0,0 +1,112 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 31 Jan 2022 12:07:43 -0500
|
||||
Subject: M98: Vulkan: Fix vkCmdResolveImage extents
|
||||
|
||||
The source framebuffer's extents were accidentally used instead of the
|
||||
blit area extents.
|
||||
|
||||
Bug: chromium:1288020
|
||||
Change-Id: I5c6128a191deeea2f972dc7f010be9d40c674ce6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3457022
|
||||
Reviewed-by: Tim Van Patten <timvp@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
index 7d088be90bc7a384ec7d6934bccddea28f8cfa0a..892983bd1ad52c6e0080c977022689c1d6a20ac5 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
@@ -1459,8 +1459,8 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
|
||||
resolveRegion.dstOffset.x = params.destOffset[0];
|
||||
resolveRegion.dstOffset.y = params.destOffset[1];
|
||||
resolveRegion.dstOffset.z = 0;
|
||||
- resolveRegion.extent.width = params.srcExtents[0];
|
||||
- resolveRegion.extent.height = params.srcExtents[1];
|
||||
+ resolveRegion.extent.width = params.blitArea.width;
|
||||
+ resolveRegion.extent.height = params.blitArea.height;
|
||||
resolveRegion.extent.depth = 1;
|
||||
|
||||
vk::PerfCounters &perfCounters = contextVk->getPerfCounters();
|
||||
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
|
||||
index dddb58fd10e4671e179f1db21781c750d7234460..72e32c27efabe8393ae840a9fef4ce37b3c5088c 100644
|
||||
--- a/src/tests/angle_end2end_tests_expectations.txt
|
||||
+++ b/src/tests/angle_end2end_tests_expectations.txt
|
||||
@@ -68,6 +68,7 @@
|
||||
// the test says. The test also fails on Intel/Vulkan/Windows.
|
||||
6068 INTEL VULKAN : MultiviewRenderPrimitiveTest.LineLoop/* = SKIP
|
||||
6068 INTEL VULKAN : MultiviewRenderPrimitiveTest.LineStrip/* = SKIP
|
||||
+6962 WIN INTEL VULKAN : BlitFramebufferTestES31.PartialResolve/* = SKIP
|
||||
|
||||
// Mac
|
||||
6025 MAC AMD OPENGL : IndexBufferOffsetTestES3.UseAsUBOThenUpdateThenUInt8Index/* = SKIP
|
||||
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
index 61f462cf4ce20b6fe14e7cab7c77b1498c1c2aa3..02f7d025d52f50fd067aea1b8ef1057afdfd4657 100644
|
||||
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
@@ -2632,6 +2632,67 @@ TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixel)
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
}
|
||||
|
||||
+// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was using the src extents
|
||||
+// as the resolve area instead of the area passed to glBlitFramebuffer.
|
||||
+TEST_P(BlitFramebufferTestES31, PartialResolve)
|
||||
+{
|
||||
+ constexpr GLint kWidth = 16;
|
||||
+ constexpr GLint kHeight = 32;
|
||||
+
|
||||
+ // Read framebuffer is multisampled.
|
||||
+ GLTexture readTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, readTexture);
|
||||
+ glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, GL_TRUE);
|
||||
+
|
||||
+ GLFramebuffer readFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
+ readTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(1, 0, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ // Draw framebuffer is single sampled. It's bound to a texture with base level the same size as
|
||||
+ // the read framebuffer, but it's bound to mip 1.
|
||||
+ GLTexture drawTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D, drawTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ nullptr);
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D);
|
||||
+
|
||||
+ GLFramebuffer drawFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawTexture, 1);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(0, 1, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kHeight / 2, GLColor::green);
|
||||
+
|
||||
+ constexpr GLint kResolveX0 = 1;
|
||||
+ constexpr GLint kResolveY0 = 2;
|
||||
+ constexpr GLint kResolveX1 = 4;
|
||||
+ constexpr GLint kResolveY1 = 6;
|
||||
+
|
||||
+ // Resolve only a portion of the read framebuffer.
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
|
||||
+ glBlitFramebuffer(kResolveX0, kResolveY0, kResolveX1, kResolveY1, kResolveX0, kResolveY0,
|
||||
+ kResolveX1, kResolveY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kResolveY0, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kResolveX0, kHeight / 2, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(kResolveX1, 0, kWidth / 2 - kResolveX1, kHeight / 2, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, kResolveY1, kWidth / 2, kHeight / 2 - kResolveY1, GLColor::green);
|
||||
+
|
||||
+ EXPECT_PIXEL_RECT_EQ(kResolveX0, kResolveY0, kResolveX1 - kResolveX0, kResolveY1 - kResolveY0,
|
||||
+ GLColor::red);
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BlitFramebufferANGLETest);
|
||||
109
patches/angle/m98_vulkan_fix_vkcmdresolveimage_offsets.patch
Normal file
109
patches/angle/m98_vulkan_fix_vkcmdresolveimage_offsets.patch
Normal file
@@ -0,0 +1,109 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 7 Feb 2022 13:46:46 -0500
|
||||
Subject: M98: Vulkan: Fix vkCmdResolveImage offsets
|
||||
|
||||
glBlitFramebuffer takes identical regions for src and dst when
|
||||
resolving. vkCmdResolveImage should use the clipped area instead of
|
||||
using the actual offsets passed to this function.
|
||||
|
||||
Bug: chromium:1292537
|
||||
Change-Id: If283a8acbca3249b771facbc30bd9f8080a03656
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3457023
|
||||
Reviewed-by: Tim Van Patten <timvp@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
index 892983bd1ad52c6e0080c977022689c1d6a20ac5..7fc8e785af2c9c50f624790eccf5f57ce4af2c87 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
@@ -1451,13 +1451,13 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
|
||||
resolveRegion.srcSubresource.mipLevel = 0;
|
||||
resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
|
||||
resolveRegion.srcSubresource.layerCount = 1;
|
||||
- resolveRegion.srcOffset.x = params.srcOffset[0];
|
||||
- resolveRegion.srcOffset.y = params.srcOffset[1];
|
||||
+ resolveRegion.srcOffset.x = params.blitArea.x;
|
||||
+ resolveRegion.srcOffset.y = params.blitArea.y;
|
||||
resolveRegion.srcOffset.z = 0;
|
||||
resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
resolveRegion.dstSubresource.layerCount = 1;
|
||||
- resolveRegion.dstOffset.x = params.destOffset[0];
|
||||
- resolveRegion.dstOffset.y = params.destOffset[1];
|
||||
+ resolveRegion.dstOffset.x = params.blitArea.x;
|
||||
+ resolveRegion.dstOffset.y = params.blitArea.y;
|
||||
resolveRegion.dstOffset.z = 0;
|
||||
resolveRegion.extent.width = params.blitArea.width;
|
||||
resolveRegion.extent.height = params.blitArea.height;
|
||||
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
|
||||
index 72e32c27efabe8393ae840a9fef4ce37b3c5088c..87041f3b43a9ab50a0ec87ea4c338b498024b1b5 100644
|
||||
--- a/src/tests/angle_end2end_tests_expectations.txt
|
||||
+++ b/src/tests/angle_end2end_tests_expectations.txt
|
||||
@@ -15,6 +15,8 @@
|
||||
6142 VULKAN : BlitFramebufferTest.BlitDepthStencilPixelByPixel/* = SKIP
|
||||
6153 VULKAN WIN INTEL : GLSLTest_ES31.StructAndArrayEqualOperator/ES3_1_Vulkan_DirectSPIRVGen = SKIP
|
||||
6153 VULKAN PIXEL4ORXL : GLSLTest_ES31.StructAndArrayEqualOperator/ES3_1_Vulkan_DirectSPIRVGen = SKIP
|
||||
+6989 OPENGL : BlitFramebufferTestES31.OOBResolve/* = SKIP
|
||||
+6989 GLES : BlitFramebufferTestES31.OOBResolve/* = SKIP
|
||||
|
||||
// SPIR-V generation doesn't yet support bools in interface blocks
|
||||
4889 VULKAN : GLSLTest.NestedSequenceOperatorWithTernaryInside/ES2_Vulkan_DirectSPIRVGen = SKIP
|
||||
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
index 02f7d025d52f50fd067aea1b8ef1057afdfd4657..ae2844d072ee5ab4c584bfa663b955994c011b0c 100644
|
||||
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
@@ -2632,6 +2632,55 @@ TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixel)
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
}
|
||||
|
||||
+// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was used with
|
||||
+// out-of-bounds regions.
|
||||
+TEST_P(BlitFramebufferTestES31, OOBResolve)
|
||||
+{
|
||||
+ constexpr GLint kWidth = 16;
|
||||
+ constexpr GLint kHeight = 32;
|
||||
+
|
||||
+ // Read framebuffer is multisampled.
|
||||
+ GLTexture readTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, readTexture);
|
||||
+ glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, GL_TRUE);
|
||||
+
|
||||
+ GLFramebuffer readFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
+ readTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(1, 0, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ // Draw framebuffer is single sampled.
|
||||
+ GLTexture drawTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D, drawTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ nullptr);
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D);
|
||||
+
|
||||
+ GLFramebuffer drawFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(0, 1, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
|
||||
+
|
||||
+ // Resolve the read framebuffer, using bounds that are outside the size of the image.
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
|
||||
+ glBlitFramebuffer(-kWidth * 2, -kHeight * 3, kWidth * 11, kHeight * 8, -kWidth * 2,
|
||||
+ -kHeight * 3, kWidth * 11, kHeight * 8, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
|
||||
+}
|
||||
+
|
||||
// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was using the src extents
|
||||
// as the resolve area instead of the area passed to glBlitFramebuffer.
|
||||
TEST_P(BlitFramebufferTestES31, PartialResolve)
|
||||
@@ -112,7 +112,6 @@ cherry-pick-3a5bafa35def.patch
|
||||
cherry-pick-b2c4e4dc21e5.patch
|
||||
m90-lts_prevents_non-browser_processes_from_requesting_memory.patch
|
||||
check_direction_of_rtcencodedframes.patch
|
||||
mas_gate_private_enterprise_APIs
|
||||
cherry-pick-c69dddfe1cde.patch
|
||||
speculative_fix_for_eye_dropper_getcolor_crash.patch
|
||||
cherry-pick-0894af410c4e.patch
|
||||
@@ -126,4 +125,31 @@ introduce_crossthreadcopier_skbitmap.patch
|
||||
allow_null_skbitmap_to_be_transferred_across_threads.patch
|
||||
use_weakptrs_for_the_threadediconloader_s_background_tasks.patch
|
||||
cherry-pick-a5f54612590d.patch
|
||||
mas_gate_private_enterprise_APIs.patch
|
||||
fix_aspect_ratio_with_max_size.patch
|
||||
cherry-pick-f0a63e1f361f.patch
|
||||
cherry-pick-27eb11a28555.patch
|
||||
cherry-pick-f781748dcb3c.patch
|
||||
sandbox_fix_sandbox_inheritance_m96_merge.patch
|
||||
cherry-pick-dbde8795233a.patch
|
||||
cherry-pick-da11d71a0227.patch
|
||||
m96_fileapi_move_origin_checks_in_bloburlstore_sooner.patch
|
||||
cherry-pick-6bb320d134b1.patch
|
||||
cherry-pick-c5571653d932.patch
|
||||
cherry-pick-1282354.patch
|
||||
cherry-pick-9db9911e1242.patch
|
||||
cherry-pick-22f27676515e.patch
|
||||
cherry-pick-1283371.patch
|
||||
cherry-pick-1283375.patch
|
||||
cherry-pick-1283198.patch
|
||||
cherry-pick-1284367.patch
|
||||
cherry-pick-be50c60b4225.patch
|
||||
cherry-pick-e3805f29fed7.patch
|
||||
m98_fs_fix_fileutil_lifetime_issue.patch
|
||||
cherry-pick-0081bb347e67.patch
|
||||
cleanup_pausablecriptexecutor_usage.patch
|
||||
cherry-pick-ebc188ad769e.patch
|
||||
cherry-pick-1277917.patch
|
||||
cherry-pick-62142d222a80.patch
|
||||
cherry-pick-1887414c016d.patch
|
||||
cherry-pick-6b2643846ae3.patch
|
||||
|
||||
26
patches/chromium/cherry-pick-0081bb347e67.patch
Normal file
26
patches/chromium/cherry-pick-0081bb347e67.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Reynolds <mattreynolds@google.com>
|
||||
Date: Wed, 19 Jan 2022 21:03:08 +0000
|
||||
Subject: gamepad: Return an invalid handle after ReportBadMessage
|
||||
|
||||
Bug: 1285449
|
||||
Change-Id: I746c539577f7bdf69cbe4212ac380e0c92a5c771
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3373944
|
||||
Auto-Submit: Matt Reynolds <mattreynolds@chromium.org>
|
||||
Reviewed-by: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#961125}
|
||||
|
||||
diff --git a/device/gamepad/gamepad_monitor.cc b/device/gamepad/gamepad_monitor.cc
|
||||
index ce8ba1ef7551e52f8ae4d9a112a08308ab2ce51c..28082924e632a895fc5bc4725bc6de3d6ca120ac 100644
|
||||
--- a/device/gamepad/gamepad_monitor.cc
|
||||
+++ b/device/gamepad/gamepad_monitor.cc
|
||||
@@ -53,6 +53,8 @@ void GamepadMonitor::GamepadStartPolling(GamepadStartPollingCallback callback) {
|
||||
GamepadService* service = GamepadService::GetInstance();
|
||||
if (!service->ConsumerBecameActive(this)) {
|
||||
mojo::ReportBadMessage("GamepadMonitor::GamepadStartPolling failed");
|
||||
+ std::move(callback).Run(base::ReadOnlySharedMemoryRegion());
|
||||
+ return;
|
||||
}
|
||||
std::move(callback).Run(service->DuplicateSharedMemoryRegion());
|
||||
}
|
||||
176
patches/chromium/cherry-pick-1277917.patch
Normal file
176
patches/chromium/cherry-pick-1277917.patch
Normal file
@@ -0,0 +1,176 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Pelchat <spelchat@chromium.org>
|
||||
Date: Fri, 7 Jan 2022 20:00:37 +0000
|
||||
Subject: Avoid UAF on StreamingSearchPrefetchURLLoader.
|
||||
|
||||
StreamingSearchPrefetchURLLoader::OnDataAvailable used to "delete this",
|
||||
which results in deleting the DataPipeDrainer, which will then be used
|
||||
once OnDataAvailable returns. Instead, we post a task to delete the
|
||||
URL loader later on.
|
||||
|
||||
Bug: 1277917
|
||||
Change-Id: I8d78c73a01fff0315b96ccb0e7fe605884b99823
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3365387
|
||||
Reviewed-by: Max Curran <curranmax@chromium.org>
|
||||
Reviewed-by: Robert Ogden <robertogden@chromium.org>
|
||||
Commit-Queue: Simon Pelchat <spelchat@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956628}
|
||||
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
index 1d3d1ea93c026d371a6ad5678e8ff37dc58f8423..e3eaad96fbada18211f295988c07d218ab67921f 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h"
|
||||
|
||||
#include "chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h"
|
||||
+#include "streaming_search_prefetch_request.h"
|
||||
|
||||
StreamingSearchPrefetchRequest::StreamingSearchPrefetchRequest(
|
||||
const GURL& prefetch_url,
|
||||
@@ -19,7 +20,9 @@ void StreamingSearchPrefetchRequest::StartPrefetchRequestInternal(
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
const net::NetworkTrafficAnnotationTag& network_traffic_annotation) {
|
||||
streaming_url_loader_ = std::make_unique<StreamingSearchPrefetchURLLoader>(
|
||||
- this, profile, std::move(resource_request), network_traffic_annotation);
|
||||
+ this, profile, std::move(resource_request), network_traffic_annotation,
|
||||
+ base::BindOnce(&StreamingSearchPrefetchRequest::StopPrefetch,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
std::unique_ptr<SearchPrefetchURLLoader>
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
index ff051c61e9cbed67d5cffbcac007d6c12a26cc76..ad75d404abe9e743d079725ffd8b01d3a49ae017 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
@@ -47,6 +47,8 @@ class StreamingSearchPrefetchRequest : public BaseSearchPrefetchRequest {
|
||||
private:
|
||||
// The ongoing prefetch request. Null before and after the fetch.
|
||||
std::unique_ptr<StreamingSearchPrefetchURLLoader> streaming_url_loader_;
|
||||
+
|
||||
+ base::WeakPtrFactory<StreamingSearchPrefetchRequest> weak_factory_{this};
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_STREAMING_SEARCH_PREFETCH_REQUEST_H_
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
index 09a8f5c444c5346dd6d2544c403a4b844e0ba781..2134bdbd2514d86b912b83480ca90242d7f7455e 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
@@ -26,15 +26,18 @@
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
#include "services/network/public/mojom/early_hints.mojom.h"
|
||||
#include "services/network/public/mojom/url_response_head.mojom.h"
|
||||
+#include "streaming_search_prefetch_url_loader.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
StreamingSearchPrefetchURLLoader::StreamingSearchPrefetchURLLoader(
|
||||
StreamingSearchPrefetchRequest* streaming_prefetch_request,
|
||||
Profile* profile,
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
- const net::NetworkTrafficAnnotationTag& network_traffic_annotation)
|
||||
+ const net::NetworkTrafficAnnotationTag& network_traffic_annotation,
|
||||
+ base::OnceClosure stop_prefetch_closure)
|
||||
: resource_request_(std::move(resource_request)),
|
||||
- streaming_prefetch_request_(streaming_prefetch_request) {
|
||||
+ streaming_prefetch_request_(streaming_prefetch_request),
|
||||
+ stop_prefetch_closure_(std::move(stop_prefetch_closure)) {
|
||||
DCHECK(streaming_prefetch_request_);
|
||||
auto url_loader_factory = profile->GetDefaultStoragePartition()
|
||||
->GetURLLoaderFactoryForBrowserProcess();
|
||||
@@ -130,7 +133,7 @@ void StreamingSearchPrefetchURLLoader::OnReceiveRedirect(
|
||||
if (streaming_prefetch_request_) {
|
||||
streaming_prefetch_request_->ErrorEncountered();
|
||||
} else {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +216,7 @@ void StreamingSearchPrefetchURLLoader::OnStartLoadingResponseBodyFromData() {
|
||||
mojo::CreateDataPipe(&options, producer_handle_, consumer_handle);
|
||||
|
||||
if (rv != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -235,7 +238,7 @@ void StreamingSearchPrefetchURLLoader::OnHandleReady(
|
||||
MojoResult result,
|
||||
const mojo::HandleSignalsState& state) {
|
||||
if (result != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
PushData();
|
||||
@@ -261,7 +264,7 @@ void StreamingSearchPrefetchURLLoader::PushData() {
|
||||
}
|
||||
|
||||
if (result != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,16 +351,24 @@ void StreamingSearchPrefetchURLLoader::OnURLLoaderMojoDisconnect() {
|
||||
DCHECK(streaming_prefetch_request_);
|
||||
streaming_prefetch_request_->ErrorEncountered();
|
||||
} else {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
void StreamingSearchPrefetchURLLoader::OnURLLoaderClientMojoDisconnect() {
|
||||
DCHECK(forwarding_client_);
|
||||
DCHECK(!streaming_prefetch_request_);
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
|
||||
void StreamingSearchPrefetchURLLoader::ClearOwnerPointer() {
|
||||
streaming_prefetch_request_ = nullptr;
|
||||
}
|
||||
+
|
||||
+void StreamingSearchPrefetchURLLoader::PostTaskToStopPrefetchAndDeleteSelf() {
|
||||
+ // To avoid UAF bugs, post a separate task to delete this object.
|
||||
+ if (stop_prefetch_closure_) {
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE, std::move(stop_prefetch_closure_));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
index 2213fb079e3f29566d67030dd2fa399ce11024e2..ed225db0b4d2b0d24aae967f320a7010c1a45044 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
@@ -39,7 +39,8 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
StreamingSearchPrefetchRequest* streaming_prefetch_request,
|
||||
Profile* profile,
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
- const net::NetworkTrafficAnnotationTag& network_traffic_annotation);
|
||||
+ const net::NetworkTrafficAnnotationTag& network_traffic_annotation,
|
||||
+ base::OnceClosure stop_prefetch_closure);
|
||||
|
||||
~StreamingSearchPrefetchURLLoader() override;
|
||||
|
||||
@@ -105,6 +106,9 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
// Clears |producer_handle_| and |handle_watcher_|.
|
||||
void Finish();
|
||||
|
||||
+ // Post a task to delete this object by running stop_prefetch_closure_.
|
||||
+ void PostTaskToStopPrefetchAndDeleteSelf();
|
||||
+
|
||||
// Sets up mojo forwarding to the navigation path. Resumes
|
||||
// |network_url_loader_| calls. Serves the start of the response to the
|
||||
// navigation path. After this method is called, |this| manages its own
|
||||
@@ -164,6 +168,9 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
mojo::ScopedDataPipeProducerHandle producer_handle_;
|
||||
std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
|
||||
|
||||
+ // Closure to cancel this prefetch. Running this callback will destroy |this|.
|
||||
+ base::OnceClosure stop_prefetch_closure_;
|
||||
+
|
||||
base::WeakPtrFactory<StreamingSearchPrefetchURLLoader> weak_factory_{this};
|
||||
};
|
||||
|
||||
31
patches/chromium/cherry-pick-1282354.patch
Normal file
31
patches/chromium/cherry-pick-1282354.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Bookholt <bookholt@chromium.org>
|
||||
Date: Tue, 11 Jan 2022 00:33:53 +0000
|
||||
Subject: ServiceWorkerContainerHost::EnsureFileAccess: abort request
|
||||
processing if the requesting process lacks file access
|
||||
|
||||
Bug: 1282354
|
||||
Change-Id: Ia37ef5b97eedb0d2ad25ffe2869844a40e5be862
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3379268
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Chris Bookholt <bookholt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#957344}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc
|
||||
index 5aca9f432a9efdb9739363e80b52233339529a1c..8b15f204e457904423da33b01bead1b03b59597a 100644
|
||||
--- a/content/browser/service_worker/service_worker_container_host.cc
|
||||
+++ b/content/browser/service_worker/service_worker_container_host.cc
|
||||
@@ -375,10 +375,12 @@ void ServiceWorkerContainerHost::EnsureFileAccess(
|
||||
ChildProcessSecurityPolicyImpl* policy =
|
||||
ChildProcessSecurityPolicyImpl::GetInstance();
|
||||
for (const auto& file : file_paths) {
|
||||
- if (!policy->CanReadFile(process_id_, file))
|
||||
+ if (!policy->CanReadFile(process_id_, file)) {
|
||||
mojo::ReportBadMessage(
|
||||
"The renderer doesn't have access to the file "
|
||||
"but it tried to grant access to the controller.");
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (!policy->CanReadFile(controller_process_id, file))
|
||||
policy->GrantReadFile(controller_process_id, file);
|
||||
28
patches/chromium/cherry-pick-1283198.patch
Normal file
28
patches/chromium/cherry-pick-1283198.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Hosseinian <dhoss@chromium.org>
|
||||
Date: Thu, 30 Dec 2021 05:08:29 +0000
|
||||
Subject: CHECK page on thumbnail requests
|
||||
|
||||
Elevate DCHECK to CHECK.
|
||||
|
||||
Fixed: 1283198
|
||||
Change-Id: Iacb3da961cfb44f94f7a377e225270a57809ef9c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3361538
|
||||
Auto-Submit: Daniel Hosseinian <dhoss@chromium.org>
|
||||
Reviewed-by: K. Moon <kmoon@chromium.org>
|
||||
Commit-Queue: K. Moon <kmoon@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#954552}
|
||||
|
||||
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
|
||||
index 7f70791ceddf298d2c95ca3569799a0f4d3746a3..c7ae1b65d416024a7d90e377a57b5ae1ea3e0c07 100644
|
||||
--- a/pdf/pdfium/pdfium_engine.cc
|
||||
+++ b/pdf/pdfium/pdfium_engine.cc
|
||||
@@ -4224,7 +4224,7 @@ void PDFiumEngine::SetLinkUnderCursorForAnnotation(FPDF_ANNOTATION annot,
|
||||
void PDFiumEngine::RequestThumbnail(int page_index,
|
||||
float device_pixel_ratio,
|
||||
SendThumbnailCallback send_callback) {
|
||||
- DCHECK(PageIndexInBounds(page_index));
|
||||
+ CHECK(PageIndexInBounds(page_index));
|
||||
pages_[page_index]->RequestThumbnail(device_pixel_ratio,
|
||||
std::move(send_callback));
|
||||
}
|
||||
138
patches/chromium/cherry-pick-1283371.patch
Normal file
138
patches/chromium/cherry-pick-1283371.patch
Normal file
@@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Clark DuVall <cduvall@chromium.org>
|
||||
Date: Thu, 6 Jan 2022 01:21:21 +0000
|
||||
Subject: Fix lifetime bug in PrefetchURLLoader
|
||||
|
||||
PrefetchURLLoader is now owned by PrefetchURLLoaderService, which is no
|
||||
longer refcounted. This makes the lifetime much easier to reason about.
|
||||
|
||||
Bug: 1283371
|
||||
Change-Id: Iaa58c1f44cc9f066459ce344012f57faca533197
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3361198
|
||||
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
|
||||
Reviewed-by: Kunihiko Sakamoto <ksakamoto@chromium.org>
|
||||
Commit-Queue: Clark DuVall <cduvall@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#955986}
|
||||
|
||||
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc
|
||||
index 5211d5552d6b2e1c1967d7dd6c6079001fef6895..345bf021541a121ea183ba16fa7ed76373f0dfd1 100644
|
||||
--- a/content/browser/loader/prefetch_url_loader_service.cc
|
||||
+++ b/content/browser/loader/prefetch_url_loader_service.cc
|
||||
@@ -202,29 +202,25 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
|
||||
->prefetched_signed_exchange_cache;
|
||||
}
|
||||
|
||||
- // For now we make self owned receiver for the loader to the request, while we
|
||||
- // can also possibly make the new loader owned by the factory so that they can
|
||||
- // live longer than the client (i.e. run in detached mode).
|
||||
- // TODO(kinuko): Revisit this.
|
||||
- mojo::MakeSelfOwnedReceiver(
|
||||
- std::make_unique<PrefetchURLLoader>(
|
||||
- request_id, options, current_context.frame_tree_node_id,
|
||||
- resource_request,
|
||||
- resource_request.trusted_params
|
||||
- ? resource_request.trusted_params->isolation_info
|
||||
- .network_isolation_key()
|
||||
- : current_context.render_frame_host->GetNetworkIsolationKey(),
|
||||
- std::move(client), traffic_annotation,
|
||||
- std::move(network_loader_factory_to_use),
|
||||
- base::BindRepeating(
|
||||
- &PrefetchURLLoaderService::CreateURLLoaderThrottles, this,
|
||||
- resource_request, current_context.frame_tree_node_id),
|
||||
- browser_context_, signed_exchange_prefetch_metric_recorder_,
|
||||
- std::move(prefetched_signed_exchange_cache), accept_langs_,
|
||||
- base::BindOnce(
|
||||
- &PrefetchURLLoaderService::GenerateRecursivePrefetchToken, this,
|
||||
- current_context.weak_ptr_factory.GetWeakPtr())),
|
||||
- std::move(receiver));
|
||||
+ // base::Unretained is safe here since |this| owns the loader.
|
||||
+ auto loader = std::make_unique<PrefetchURLLoader>(
|
||||
+ request_id, options, current_context.frame_tree_node_id, resource_request,
|
||||
+ resource_request.trusted_params
|
||||
+ ? resource_request.trusted_params->isolation_info
|
||||
+ .network_isolation_key()
|
||||
+ : current_context.render_frame_host->GetNetworkIsolationKey(),
|
||||
+ std::move(client), traffic_annotation,
|
||||
+ std::move(network_loader_factory_to_use),
|
||||
+ base::BindRepeating(&PrefetchURLLoaderService::CreateURLLoaderThrottles,
|
||||
+ base::Unretained(this), resource_request,
|
||||
+ current_context.frame_tree_node_id),
|
||||
+ browser_context_, signed_exchange_prefetch_metric_recorder_,
|
||||
+ std::move(prefetched_signed_exchange_cache), accept_langs_,
|
||||
+ base::BindOnce(&PrefetchURLLoaderService::GenerateRecursivePrefetchToken,
|
||||
+ base::Unretained(this),
|
||||
+ current_context.weak_ptr_factory.GetWeakPtr()));
|
||||
+ auto* raw_loader = loader.get();
|
||||
+ prefetch_receivers_.Add(raw_loader, std::move(receiver), std::move(loader));
|
||||
}
|
||||
|
||||
PrefetchURLLoaderService::~PrefetchURLLoaderService() = default;
|
||||
diff --git a/content/browser/loader/prefetch_url_loader_service.h b/content/browser/loader/prefetch_url_loader_service.h
|
||||
index 210794966c8d25947f3e6b490538c1f851d80d52..c5fff844f73deaf2912716de9cf97547c498e4e5 100644
|
||||
--- a/content/browser/loader/prefetch_url_loader_service.h
|
||||
+++ b/content/browser/loader/prefetch_url_loader_service.h
|
||||
@@ -35,13 +35,11 @@ class URLLoaderFactoryGetter;
|
||||
// prefetches. The renderer uses it for prefetch requests including <link
|
||||
// rel="prefetch">.
|
||||
class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
- : public base::RefCountedThreadSafe<
|
||||
- PrefetchURLLoaderService,
|
||||
- content::BrowserThread::DeleteOnUIThread>,
|
||||
- public blink::mojom::RendererPreferenceWatcher,
|
||||
+ : public blink::mojom::RendererPreferenceWatcher,
|
||||
public network::mojom::URLLoaderFactory {
|
||||
public:
|
||||
explicit PrefetchURLLoaderService(BrowserContext* browser_context);
|
||||
+ ~PrefetchURLLoaderService() override;
|
||||
|
||||
void GetFactory(
|
||||
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
|
||||
@@ -67,12 +65,8 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
}
|
||||
|
||||
private:
|
||||
- friend class base::DeleteHelper<content::PrefetchURLLoaderService>;
|
||||
- friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
|
||||
struct BindContext;
|
||||
|
||||
- ~PrefetchURLLoaderService() override;
|
||||
-
|
||||
// network::mojom::URLLoaderFactory:
|
||||
void CreateLoaderAndStart(
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
|
||||
@@ -114,6 +108,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
mojo::ReceiverSet<network::mojom::URLLoaderFactory,
|
||||
std::unique_ptr<BindContext>>
|
||||
loader_factory_receivers_;
|
||||
+ mojo::ReceiverSet<network::mojom::URLLoader,
|
||||
+ std::unique_ptr<network::mojom::URLLoader>>
|
||||
+ prefetch_receivers_;
|
||||
// Used in the IO thread.
|
||||
mojo::Receiver<blink::mojom::RendererPreferenceWatcher>
|
||||
preference_watcher_receiver_{this};
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index 263fe6195ac6d48cd7a985ca844d1a6e421a9b1d..ac0bba6a7b41e497eb28c820476f36de5c63bc34 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1285,7 +1285,7 @@ void StoragePartitionImpl::Initialize(
|
||||
blob_context, filesystem_context_, fallback_blob_registry);
|
||||
|
||||
prefetch_url_loader_service_ =
|
||||
- base::MakeRefCounted<PrefetchURLLoaderService>(browser_context_);
|
||||
+ std::make_unique<PrefetchURLLoaderService>(browser_context_);
|
||||
|
||||
cookie_store_context_ = base::MakeRefCounted<CookieStoreContext>();
|
||||
// Unit tests use the Initialize() callback to crash early if restoring the
|
||||
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
|
||||
index 6d1c4031c340e0a16943b1f0c0efdf9f5dc5f99b..ba0ae57aae69a5edf4ce23c202a93c8cdb003051 100644
|
||||
--- a/content/browser/storage_partition_impl.h
|
||||
+++ b/content/browser/storage_partition_impl.h
|
||||
@@ -561,7 +561,7 @@ class CONTENT_EXPORT StoragePartitionImpl
|
||||
std::unique_ptr<BroadcastChannelProvider> broadcast_channel_provider_;
|
||||
std::unique_ptr<BluetoothAllowedDevicesMap> bluetooth_allowed_devices_map_;
|
||||
scoped_refptr<BlobRegistryWrapper> blob_registry_;
|
||||
- scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
|
||||
+ std::unique_ptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
|
||||
scoped_refptr<CookieStoreContext> cookie_store_context_;
|
||||
scoped_refptr<BucketContext> bucket_context_;
|
||||
scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
|
||||
74
patches/chromium/cherry-pick-1283375.patch
Normal file
74
patches/chromium/cherry-pick-1283375.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alan Screen <awscreen@chromium.org>
|
||||
Date: Fri, 7 Jan 2022 09:38:01 +0000
|
||||
Subject: Ensure valid print render host before proceeding to print.
|
||||
|
||||
Bug: 1283375
|
||||
Change-Id: I5691fc2a9d09040e777aafd0061b957025643b8a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3369086
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Alan Screen <awscreen@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956443}
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
|
||||
index bfed66e625f1d6e53b31750cd7d5fa7748cae75c..6c5ec9086264972ff67beab712ae2695ffa93395 100644
|
||||
--- a/chrome/browser/printing/print_view_manager.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager.cc
|
||||
@@ -91,6 +91,11 @@ bool PrintViewManager::PrintForSystemDialogNow(
|
||||
on_print_dialog_shown_callback_ = std::move(dialog_shown_callback);
|
||||
is_switching_to_system_dialog_ = true;
|
||||
|
||||
+ // Remember the ID for `print_preview_rfh_`, to enable checking that the
|
||||
+ // `RenderFrameHost` is still valid after a possible inner message loop runs
|
||||
+ // in `DisconnectFromCurrentPrintJob()`.
|
||||
+ content::GlobalRenderFrameHostId rfh_id = print_preview_rfh_->GetGlobalId();
|
||||
+
|
||||
auto weak_this = weak_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
if (!weak_this)
|
||||
@@ -100,6 +105,10 @@ bool PrintViewManager::PrintForSystemDialogNow(
|
||||
if (IsCrashed())
|
||||
return false;
|
||||
|
||||
+ // Don't print if `print_preview_rfh_` is no longer live.
|
||||
+ if (!content::RenderFrameHost::FromID(rfh_id))
|
||||
+ return false;
|
||||
+
|
||||
// TODO(crbug.com/809738) Register with `PrintBackendServiceManager` when
|
||||
// system print is enabled out-of-process.
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
||||
index 562800bf194e1f07f58b912b54a740b7c7dcabb6..c34f3ba9bb4adbfa8f190d5ef75cfa72937f0b1d 100644
|
||||
--- a/chrome/browser/printing/print_view_manager_base.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "components/services/print_compositor/public/cpp/print_service_mojo_types.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
+#include "content/public/browser/global_routing_id.h"
|
||||
#include "content/public/browser/notification_details.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_source.h"
|
||||
@@ -364,6 +365,11 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
|
||||
bool silent,
|
||||
base::Value settings,
|
||||
CompletionCallback callback) {
|
||||
+ // Remember the ID for `rfh`, to enable checking that the `RenderFrameHost`
|
||||
+ // is still valid after a possible inner message loop runs in
|
||||
+ // `DisconnectFromCurrentPrintJob()`.
|
||||
+ content::GlobalRenderFrameHostId rfh_id = rfh->GetGlobalId();
|
||||
+
|
||||
auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
if (!weak_this)
|
||||
@@ -373,6 +379,10 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
|
||||
if (IsCrashed())
|
||||
return false;
|
||||
|
||||
+ // Don't print if `rfh` is no longer live.
|
||||
+ if (!content::RenderFrameHost::FromID(rfh_id))
|
||||
+ return false;
|
||||
+
|
||||
// TODO(crbug.com/809738) Register with `PrintBackendServiceManager` when
|
||||
// system print is enabled out-of-process. A corresponding unregister should
|
||||
// go in `ReleasePrintJob()`.
|
||||
188
patches/chromium/cherry-pick-1284367.patch
Normal file
188
patches/chromium/cherry-pick-1284367.patch
Normal file
@@ -0,0 +1,188 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xinghui Lu <xinghuilu@chromium.org>
|
||||
Date: Thu, 6 Jan 2022 08:36:45 +0000
|
||||
Subject: Use RFH global id to ensure the RFH is valid.
|
||||
|
||||
Observing via RenderFrameDeleted and RenderFrameHostChanged is not
|
||||
sufficient for validating the RFH is still valid, because the frames
|
||||
can belong to inner WebContents. As suggested in
|
||||
https://crrev.com/c/2449389, storing a GlobalFrameRoutingId is the
|
||||
preferred method of keeping a reference to a RFH.
|
||||
|
||||
Bug: 1284367
|
||||
Change-Id: I3afb40e394d6e2e7fd19b2704e0dd68fa23c7bb2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3367466
|
||||
Reviewed-by: Daniel Rubery <drubery@chromium.org>
|
||||
Commit-Queue: Xinghui Lu <xinghuilu@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956061}
|
||||
|
||||
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
index 4ba3daa516121e73ead560fd3ba9d6e011ceadc7..c7ca2f45eb8afdb2713630e507733741bf4a8307 100644
|
||||
--- a/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
+++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
@@ -596,7 +596,8 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails) {
|
||||
parent_node->children.push_back(GURL(kDOMChildURL));
|
||||
params.push_back(std::move(parent_node));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -815,10 +816,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(),
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params_copy));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params_copy));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params_copy));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -864,9 +866,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(outer_params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -990,9 +994,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_AmbiguousDOM) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(outer_params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(outer_params));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params));
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
ClientSafeBrowsingReportRequest actual;
|
||||
@@ -1257,10 +1263,10 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_TrimToAdTags) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), child_rfh,
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), child_rfh->GetGlobalId(),
|
||||
std::move(inner_params));
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), main_rfh(),
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
@@ -1333,10 +1339,10 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_EmptyReportNotSent) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), child_rfh,
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), child_rfh->GetGlobalId(),
|
||||
std::move(inner_params));
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), main_rfh(),
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
@@ -1593,7 +1599,8 @@ TEST_F(ThreatDetailsTest, HTTPCache) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1673,7 +1680,8 @@ TEST_F(ThreatDetailsTest, HttpsResourceSanitization) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1756,7 +1764,8 @@ TEST_F(ThreatDetailsTest, HTTPCacheNoEntries) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1815,7 +1824,8 @@ TEST_F(ThreatDetailsTest, HistoryServiceUrls) {
|
||||
// The redirects collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the redirects callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
diff --git a/components/safe_browsing/content/browser/threat_details.cc b/components/safe_browsing/content/browser/threat_details.cc
|
||||
index f3fe647b5d443c2a2f284289ae66d81782c5f6e8..361830189b0ab6324fe87719f36f2fa0bc948224 100644
|
||||
--- a/components/safe_browsing/content/browser/threat_details.cc
|
||||
+++ b/components/safe_browsing/content/browser/threat_details.cc
|
||||
@@ -664,16 +664,20 @@ void ThreatDetails::RequestThreatDOMDetails(content::RenderFrameHost* frame) {
|
||||
pending_render_frame_hosts_.push_back(frame);
|
||||
raw_threat_report->GetThreatDOMDetails(
|
||||
base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, GetWeakPtr(),
|
||||
- std::move(threat_reporter), frame));
|
||||
+ std::move(threat_reporter), frame->GetGlobalId()));
|
||||
}
|
||||
|
||||
// When the renderer is done, this is called.
|
||||
void ThreatDetails::OnReceivedThreatDOMDetails(
|
||||
mojo::Remote<mojom::ThreatReporter> threat_reporter,
|
||||
- content::RenderFrameHost* sender,
|
||||
+ content::GlobalRenderFrameHostId sender_id,
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params) {
|
||||
// If the RenderFrameHost was closed between sending the IPC and this callback
|
||||
// running, |sender| will be invalid.
|
||||
+ auto* sender = content::RenderFrameHost::FromID(sender_id);
|
||||
+ if (!sender) {
|
||||
+ return;
|
||||
+ }
|
||||
const auto sender_it = std::find(pending_render_frame_hosts_.begin(),
|
||||
pending_render_frame_hosts_.end(), sender);
|
||||
if (sender_it == pending_render_frame_hosts_.end()) {
|
||||
diff --git a/components/safe_browsing/content/browser/threat_details.h b/components/safe_browsing/content/browser/threat_details.h
|
||||
index 8cb89700141561aab49edc474799c9e7148b8ae8..61dcb8d9c772d223661236d99aebd1d3ebe01d3a 100644
|
||||
--- a/components/safe_browsing/content/browser/threat_details.h
|
||||
+++ b/components/safe_browsing/content/browser/threat_details.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "components/safe_browsing/core/common/proto/csd.pb.h"
|
||||
#include "components/security_interstitials/core/unsafe_resource.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
+#include "content/public/browser/global_routing_id.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
|
||||
@@ -169,7 +170,7 @@ class ThreatDetails : public content::WebContentsObserver {
|
||||
|
||||
void OnReceivedThreatDOMDetails(
|
||||
mojo::Remote<mojom::ThreatReporter> threat_reporter,
|
||||
- content::RenderFrameHost* sender,
|
||||
+ content::GlobalRenderFrameHostId sender_id,
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params);
|
||||
|
||||
void AddRedirectUrlList(const std::vector<GURL>& urls);
|
||||
53
patches/chromium/cherry-pick-1887414c016d.patch
Normal file
53
patches/chromium/cherry-pick-1887414c016d.patch
Normal file
@@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Muyao Xu <muyaoxu@google.com>
|
||||
Date: Thu, 17 Feb 2022 16:23:29 +0000
|
||||
Subject: Replace WidgetObserver::OnWidgetClosing() with OnWidgetDestroying()
|
||||
|
||||
In some cases, OnWidgetClosing() is not called when the widget is
|
||||
closed, resulting an invalid pointer |widget_| stored in
|
||||
WebContentsDisplayObserverView.
|
||||
|
||||
This CL replaces OnWidgetClosing() with OnWidgetDestroying(), which
|
||||
is recommended in crbug.com/1240365
|
||||
|
||||
(cherry picked from commit 4535fe2334d0713535adb52b641a8cb34e11333c)
|
||||
|
||||
Bug: 1291728
|
||||
Change-Id: I64fef8b30930f60220008809ee00f4385d6c3520
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3425473
|
||||
Auto-Submit: Muyao Xu <muyaoxu@google.com>
|
||||
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#965431}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3435985
|
||||
Reviewed-by: Michael Ershov <miersh@google.com>
|
||||
Owners-Override: Michael Ershov <miersh@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1480}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
index b2cd4550d26fcbe5463043181800e5d705559cb3..e2a1c772c31a3c073c8629cb745c7a5dd16174a8 100644
|
||||
--- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
+++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
@@ -64,7 +64,7 @@ void WebContentsDisplayObserverView::OnBrowserSetLastActive(Browser* browser) {
|
||||
}
|
||||
}
|
||||
|
||||
-void WebContentsDisplayObserverView::OnWidgetClosing(views::Widget* widget) {
|
||||
+void WebContentsDisplayObserverView::OnWidgetDestroying(views::Widget* widget) {
|
||||
if (widget_)
|
||||
widget_->RemoveObserver(this);
|
||||
widget_ = nullptr;
|
||||
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
index 17a8ca48b1c836a82e2be5e5c605bc1837150cba..b63cf4505318a44c65585b06ec13960bad5d9e32 100644
|
||||
--- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
+++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
@@ -28,7 +28,7 @@ class WebContentsDisplayObserverView : public WebContentsDisplayObserver,
|
||||
void OnBrowserSetLastActive(Browser* browser) override;
|
||||
|
||||
// views::WidgetObserver overrides:
|
||||
- void OnWidgetClosing(views::Widget* widget) override;
|
||||
+ void OnWidgetDestroying(views::Widget* widget) override;
|
||||
void OnWidgetBoundsChanged(views::Widget* widget,
|
||||
const gfx::Rect& new_bounds) override;
|
||||
|
||||
86
patches/chromium/cherry-pick-22f27676515e.patch
Normal file
86
patches/chromium/cherry-pick-22f27676515e.patch
Normal file
@@ -0,0 +1,86 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Christopher Cameron <ccameron@chromium.org>
|
||||
Date: Tue, 9 Nov 2021 00:23:45 +0000
|
||||
Subject: WebContentsVideoCaptureDevice: Fix use-after-free
|
||||
|
||||
The classes WebContentsVideoCaptureDevice,
|
||||
AuraWindowVideoCaptureDevice::WindowTracker, and
|
||||
ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate all keep a raw
|
||||
pointer that they use to access the MouseCursorOverlayController.
|
||||
|
||||
This raw pointer comes from the base class FrameSinkVideoCaptureDevice
|
||||
and should outlive the class that has a raw pointer. On macOS, this
|
||||
isn't necessarily the case.
|
||||
|
||||
Avoid this sharp edge by using a WeakPtr for the
|
||||
MouseCursorOverlayController, and checking that it is valid before
|
||||
using it.
|
||||
|
||||
Bug: 1252562, 1179098
|
||||
Change-Id: I1d74bea1255597662aab3f9f2430c49d2e39836a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3260842
|
||||
Commit-Queue: ccameron <ccameron@chromium.org>
|
||||
Reviewed-by: mark a. foltz <mfoltz@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#939604}
|
||||
|
||||
diff --git a/content/browser/media/capture/views_widget_video_capture_device_mac.cc b/content/browser/media/capture/views_widget_video_capture_device_mac.cc
|
||||
index fee27cebfd64ee1cddbcb9873fa4b5e67cb526fc..50da870a417c17b1999b7d98bd8c2cb82e356c06 100644
|
||||
--- a/content/browser/media/capture/views_widget_video_capture_device_mac.cc
|
||||
+++ b/content/browser/media/capture/views_widget_video_capture_device_mac.cc
|
||||
@@ -19,9 +19,10 @@ namespace content {
|
||||
class ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate
|
||||
: public remote_cocoa::ScopedCGWindowID::Observer {
|
||||
public:
|
||||
- UIThreadDelegate(uint32_t cg_window_id,
|
||||
- const base::WeakPtr<FrameSinkVideoCaptureDevice> device,
|
||||
- MouseCursorOverlayController* cursor_controller)
|
||||
+ UIThreadDelegate(
|
||||
+ uint32_t cg_window_id,
|
||||
+ const base::WeakPtr<FrameSinkVideoCaptureDevice> device,
|
||||
+ const base::WeakPtr<MouseCursorOverlayController> cursor_controller)
|
||||
: cg_window_id_(cg_window_id),
|
||||
device_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
||||
device_(device),
|
||||
@@ -83,8 +84,11 @@ class ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate
|
||||
void OnScopedCGWindowIDMouseMoved(uint32_t cg_window_id,
|
||||
const gfx::PointF& location_in_window,
|
||||
const gfx::Size& window_size) override {
|
||||
- cursor_controller_->SetTargetSize(window_size);
|
||||
- cursor_controller_->OnMouseMoved(location_in_window);
|
||||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
+ if (cursor_controller_) {
|
||||
+ cursor_controller_->SetTargetSize(window_size);
|
||||
+ cursor_controller_->OnMouseMoved(location_in_window);
|
||||
+ }
|
||||
}
|
||||
|
||||
const uint32_t cg_window_id_;
|
||||
@@ -96,20 +100,21 @@ class ViewsWidgetVideoCaptureDeviceMac::UIThreadDelegate
|
||||
|
||||
// |device_| may only be dereferenced by tasks posted to
|
||||
// |device_task_runner_|.
|
||||
- base::WeakPtr<FrameSinkVideoCaptureDevice> device_;
|
||||
+ const base::WeakPtr<FrameSinkVideoCaptureDevice> device_;
|
||||
|
||||
- // Owned by FrameSinkVideoCaptureDevice. This will be valid for the life of
|
||||
- // UIThreadDelegate because the UIThreadDelegate deleter task will be posted
|
||||
- // to the UI thread before the MouseCursorOverlayController deleter task.
|
||||
- // See similar behavior in WebContentsVideoCaptureDevice::FrameTracker.
|
||||
- MouseCursorOverlayController* const cursor_controller_;
|
||||
+ // Owned by FrameSinkVideoCaptureDevice. This may only be accessed on the
|
||||
+ // UI thread. This is not guaranteed to be valid and must be checked before
|
||||
+ // use.
|
||||
+ // https://crbug.com/1252562
|
||||
+ const base::WeakPtr<MouseCursorOverlayController> cursor_controller_;
|
||||
};
|
||||
|
||||
ViewsWidgetVideoCaptureDeviceMac::ViewsWidgetVideoCaptureDeviceMac(
|
||||
const DesktopMediaID& source_id)
|
||||
: weak_factory_(this) {
|
||||
ui_thread_delegate_ = std::make_unique<UIThreadDelegate>(
|
||||
- source_id.id, weak_factory_.GetWeakPtr(), cursor_controller());
|
||||
+ source_id.id, weak_factory_.GetWeakPtr(),
|
||||
+ cursor_controller()->GetWeakPtr());
|
||||
}
|
||||
|
||||
ViewsWidgetVideoCaptureDeviceMac::~ViewsWidgetVideoCaptureDeviceMac() {
|
||||
71
patches/chromium/cherry-pick-27eb11a28555.patch
Normal file
71
patches/chromium/cherry-pick-27eb11a28555.patch
Normal file
@@ -0,0 +1,71 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Wed, 29 Sep 2021 07:58:26 +0000
|
||||
Subject: Run CORS check for manual redirects
|
||||
|
||||
...to prevent status code leak.
|
||||
|
||||
Bug: 1251179
|
||||
Change-Id: I7fcab0daf49e16305ed53702f42d1d1eacc933e5
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3193481
|
||||
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#926166}
|
||||
|
||||
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
|
||||
index 6e4e8acf811f29712e87994e3fa125a811da978a..72aac202ca076fe7ea81f833549773f540e9b7d7 100644
|
||||
--- a/services/network/cors/cors_url_loader.cc
|
||||
+++ b/services/network/cors/cors_url_loader.cc
|
||||
@@ -303,13 +303,6 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
|
||||
DCHECK(forwarding_client_);
|
||||
DCHECK(!deferred_redirect_url_);
|
||||
|
||||
- if (request_.redirect_mode == mojom::RedirectMode::kManual) {
|
||||
- deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
|
||||
- forwarding_client_->OnReceiveRedirect(redirect_info,
|
||||
- std::move(response_head));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
// If |CORS flag| is set and a CORS check for |request| and |response| returns
|
||||
// failure, then return a network error.
|
||||
if (fetch_cors_flag_ && IsCorsEnabledRequestMode(request_.mode)) {
|
||||
@@ -327,6 +320,13 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (request_.redirect_mode == mojom::RedirectMode::kManual) {
|
||||
+ deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
|
||||
+ forwarding_client_->OnReceiveRedirect(redirect_info,
|
||||
+ std::move(response_head));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
timing_allow_failed_flag_ = !PassesTimingAllowOriginCheck(*response_head);
|
||||
|
||||
// Because we initiate a new request on redirect in some cases, we cannot
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
index eed44e0414cb8947c9b7c21df6ef288f733f8994..9f1ff98c65af97bcf185867ac6c6e128dbd77715 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
@@ -1,6 +1,7 @@
|
||||
// META: script=/common/get-host-info.sub.js
|
||||
|
||||
var redirectLocation = "cors-top.txt";
|
||||
+const { ORIGIN, REMOTE_ORIGIN } = get_host_info();
|
||||
|
||||
function testRedirect(origin, redirectStatus, redirectMode, corsMode) {
|
||||
var url = new URL("../resources/redirect.py", self.location);
|
||||
@@ -47,4 +48,12 @@ for (var origin of ["same-origin", "cross-origin"]) {
|
||||
}
|
||||
}
|
||||
|
||||
+promise_test(async (t) => {
|
||||
+ const destination = `${ORIGIN}/common/blank.html`;
|
||||
+ // We use /common/redirect.py intentionally, as we want a CORS error.
|
||||
+ const url =
|
||||
+ `${REMOTE_ORIGIN}/common/redirect.py?location=${destination}`;
|
||||
+ await promise_rejects_js(t, TypeError, fetch(url, { redirect: "manual" }));
|
||||
+}, "manual redirect with a CORS error should be rejected");
|
||||
+
|
||||
done();
|
||||
151
patches/chromium/cherry-pick-62142d222a80.patch
Normal file
151
patches/chromium/cherry-pick-62142d222a80.patch
Normal file
@@ -0,0 +1,151 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Thu, 24 Feb 2022 15:13:13 +0000
|
||||
Subject: Validate message headers sooner
|
||||
|
||||
M96 merge issues:
|
||||
- multiplex_router.h: conflict in removed lines because of
|
||||
differences in comments above header_validator_
|
||||
- connector.h: conflicting includes
|
||||
|
||||
Message header validation has been tied to interface message dispatch,
|
||||
but not all mojo::Message consumers are interface bindings.
|
||||
|
||||
mojo::Connector is a more general-purpose entry point through which
|
||||
incoming messages are received and transformed into mojo::Message
|
||||
objects. Blink's MessagePort implementation uses Connector directly to
|
||||
transmit and receive raw serialized object data.
|
||||
|
||||
This change moves MessageHeaderValidator ownership into Connector and
|
||||
always applies its validation immediately after reading a message from
|
||||
the pipe, thereby ensuring that all mojo::Message objects used in
|
||||
production have validated headers before use.
|
||||
|
||||
(cherry picked from commit 8d5bc69146505785ce299c490e35e3f3ef19f69c)
|
||||
|
||||
Fixed: 1281908
|
||||
Change-Id: Ie0e251ab04681a4fd4b849d82c247e0ed800dc04
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3462461
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#971263}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3483815
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1505}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h
|
||||
index 3975d01a434d6caf229c6d8eaedfe5e2acf684f8..ff17af9b378a1992dbd681e80e957826ebfd83dd 100644
|
||||
--- a/mojo/public/cpp/bindings/connector.h
|
||||
+++ b/mojo/public/cpp/bindings/connector.h
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "base/sequenced_task_runner.h"
|
||||
#include "mojo/public/cpp/bindings/connection_group.h"
|
||||
#include "mojo/public/cpp/bindings/message.h"
|
||||
+#include "mojo/public/cpp/bindings/message_header_validator.h"
|
||||
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
|
||||
#include "mojo/public/cpp/system/core.h"
|
||||
#include "mojo/public/cpp/system/handle_signal_tracker.h"
|
||||
@@ -345,6 +346,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) Connector : public MessageReceiver {
|
||||
// The number of pending tasks for |CallDispatchNextMessageFromPipe|.
|
||||
size_t num_pending_dispatch_tasks_ = 0;
|
||||
|
||||
+ MessageHeaderValidator header_validator_;
|
||||
+
|
||||
#if defined(ENABLE_IPC_FUZZER)
|
||||
std::unique_ptr<MessageReceiver> message_dumper_;
|
||||
#endif
|
||||
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
|
||||
index 92a9756cbaebe12377e9c9b81467260c73528311..cb08f13b1bfa13a1a79f7f39005f826e51c12a69 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/connector.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/connector.cc
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "base/rand_util.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/strcat.h"
|
||||
+#include "base/strings/string_util.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/threading/sequence_local_storage_slot.h"
|
||||
@@ -152,7 +153,11 @@ Connector::Connector(ScopedMessagePipeHandle message_pipe,
|
||||
force_immediate_dispatch_(!EnableTaskPerMessage()),
|
||||
outgoing_serialization_mode_(g_default_outgoing_serialization_mode),
|
||||
incoming_serialization_mode_(g_default_incoming_serialization_mode),
|
||||
- interface_name_(interface_name) {
|
||||
+ interface_name_(interface_name),
|
||||
+ header_validator_(
|
||||
+ base::JoinString({interface_name ? interface_name : "Generic",
|
||||
+ "MessageHeaderValidator"},
|
||||
+ "")) {
|
||||
if (config == MULTI_THREADED_SEND)
|
||||
lock_.emplace();
|
||||
|
||||
@@ -492,6 +497,7 @@ MojoResult Connector::ReadMessage(Message* message) {
|
||||
return result;
|
||||
|
||||
*message = Message::CreateFromMessageHandle(&handle);
|
||||
+
|
||||
if (message->IsNull()) {
|
||||
// Even if the read was successful, the Message may still be null if there
|
||||
// was a problem extracting handles from it. We treat this essentially as
|
||||
@@ -507,6 +513,10 @@ MojoResult Connector::ReadMessage(Message* message) {
|
||||
return MOJO_RESULT_ABORTED;
|
||||
}
|
||||
|
||||
+ if (!header_validator_.Accept(message)) {
|
||||
+ return MOJO_RESULT_ABORTED;
|
||||
+ }
|
||||
+
|
||||
return MOJO_RESULT_OK;
|
||||
}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
index 605e51344d64eb5ede3ab475bc8833b37a458535..23e3970089e33d07b18d734d4f599c9c9f9e4bc8 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
|
||||
#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
|
||||
#include "mojo/public/cpp/bindings/lib/message_quota_checker.h"
|
||||
-#include "mojo/public/cpp/bindings/message_header_validator.h"
|
||||
#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
|
||||
|
||||
namespace mojo {
|
||||
@@ -389,14 +388,7 @@ MultiplexRouter::MultiplexRouter(
|
||||
if (quota_checker)
|
||||
connector_.SetMessageQuotaChecker(std::move(quota_checker));
|
||||
|
||||
- std::unique_ptr<MessageHeaderValidator> header_validator =
|
||||
- std::make_unique<MessageHeaderValidator>();
|
||||
- header_validator_ = header_validator.get();
|
||||
- dispatcher_.SetValidator(std::move(header_validator));
|
||||
-
|
||||
if (primary_interface_name) {
|
||||
- header_validator_->SetDescription(base::JoinString(
|
||||
- {primary_interface_name, "[primary] MessageHeaderValidator"}, " "));
|
||||
control_message_handler_.SetDescription(base::JoinString(
|
||||
{primary_interface_name, "[primary] PipeControlMessageHandler"}, " "));
|
||||
}
|
||||
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
index 3d3bbb16e25b1adc678e536bd977fa22fc478920..3a9f76a57e301aa89d1bdc5aa1000f815793e238 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
@@ -38,7 +38,6 @@ class SequencedTaskRunner;
|
||||
namespace mojo {
|
||||
|
||||
class AsyncFlusher;
|
||||
-class MessageHeaderValidator;
|
||||
class PendingFlush;
|
||||
|
||||
namespace internal {
|
||||
@@ -301,9 +300,6 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) MultiplexRouter
|
||||
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
||||
|
||||
- // Owned by |dispatcher_| below.
|
||||
- MessageHeaderValidator* header_validator_ = nullptr;
|
||||
-
|
||||
MessageDispatcher dispatcher_;
|
||||
Connector connector_;
|
||||
|
||||
150
patches/chromium/cherry-pick-6b2643846ae3.patch
Normal file
150
patches/chromium/cherry-pick-6b2643846ae3.patch
Normal file
@@ -0,0 +1,150 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Date: Thu, 24 Feb 2022 17:39:53 +0000
|
||||
Subject: Guard BatchingMediaLog::event_handlers_ with lock
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It seems that despite MediaLog::OnWebMediaPlayerDestroyed and
|
||||
MediaLog::AddLogRecord both grabbing a lock,
|
||||
BatchingMediaLog::AddLogRecordLocked can escape the lock handle by
|
||||
posting BatchingMediaLog::SendQueuedMediaEvents, causing a race.
|
||||
|
||||
When the addition of an event is interrupted by the deletion of a player
|
||||
due to player culling in MediaInspectorContextImpl, a UAF can occur.
|
||||
|
||||
R=dalecurtis
|
||||
|
||||
(cherry picked from commit 34526c3d0a857a22618e4d77c7f63b5ca6f8d3d2)
|
||||
|
||||
Bug: 1295786
|
||||
Change-Id: I77df94988f806e4d98924669d27860e50455299d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3451494
|
||||
Commit-Queue: Ted (Chromium) Meyer <tmathmeyer@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#970815}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3483655
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1508}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/renderer/media/batching_media_log.cc b/content/renderer/media/batching_media_log.cc
|
||||
index 8d8c5cb28b9bb0fcebcceb9e56db98fdace13c88..2d12a5eb42b930acac74a5ea2b2961e6c7e32fcf 100644
|
||||
--- a/content/renderer/media/batching_media_log.cc
|
||||
+++ b/content/renderer/media/batching_media_log.cc
|
||||
@@ -52,9 +52,9 @@ BatchingMediaLog::BatchingMediaLog(
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
std::vector<std::unique_ptr<EventHandler>> event_handlers)
|
||||
: task_runner_(std::move(task_runner)),
|
||||
- event_handlers_(std::move(event_handlers)),
|
||||
tick_clock_(base::DefaultTickClock::GetInstance()),
|
||||
last_ipc_send_time_(tick_clock_->NowTicks()),
|
||||
+ event_handlers_(std::move(event_handlers)),
|
||||
ipc_send_pending_(false),
|
||||
logged_rate_limit_warning_(false) {
|
||||
// Pre-bind the WeakPtr on the right thread since we'll receive calls from
|
||||
@@ -76,6 +76,7 @@ BatchingMediaLog::~BatchingMediaLog() {
|
||||
}
|
||||
|
||||
void BatchingMediaLog::OnWebMediaPlayerDestroyedLocked() {
|
||||
+ base::AutoLock lock(lock_);
|
||||
for (const auto& handler : event_handlers_)
|
||||
handler->OnWebMediaPlayerDestroyed();
|
||||
}
|
||||
@@ -198,32 +199,30 @@ std::string BatchingMediaLog::MediaEventToMessageString(
|
||||
|
||||
void BatchingMediaLog::SendQueuedMediaEvents() {
|
||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||
+ base::AutoLock auto_lock(lock_);
|
||||
|
||||
- std::vector<media::MediaLogRecord> events_to_send;
|
||||
- {
|
||||
- base::AutoLock auto_lock(lock_);
|
||||
- DCHECK(ipc_send_pending_);
|
||||
- ipc_send_pending_ = false;
|
||||
-
|
||||
- if (last_duration_changed_event_) {
|
||||
- queued_media_events_.push_back(*last_duration_changed_event_);
|
||||
- last_duration_changed_event_.reset();
|
||||
- }
|
||||
+ DCHECK(ipc_send_pending_);
|
||||
+ ipc_send_pending_ = false;
|
||||
|
||||
- if (last_buffering_state_event_) {
|
||||
- queued_media_events_.push_back(*last_buffering_state_event_);
|
||||
- last_buffering_state_event_.reset();
|
||||
- }
|
||||
+ if (last_duration_changed_event_) {
|
||||
+ queued_media_events_.push_back(*last_duration_changed_event_);
|
||||
+ last_duration_changed_event_.reset();
|
||||
+ }
|
||||
|
||||
- queued_media_events_.swap(events_to_send);
|
||||
- last_ipc_send_time_ = tick_clock_->NowTicks();
|
||||
+ if (last_buffering_state_event_) {
|
||||
+ queued_media_events_.push_back(*last_buffering_state_event_);
|
||||
+ last_buffering_state_event_.reset();
|
||||
}
|
||||
|
||||
- if (events_to_send.empty())
|
||||
+ last_ipc_send_time_ = tick_clock_->NowTicks();
|
||||
+
|
||||
+ if (queued_media_events_.empty())
|
||||
return;
|
||||
|
||||
for (const auto& handler : event_handlers_)
|
||||
- handler->SendQueuedMediaEvents(events_to_send);
|
||||
+ handler->SendQueuedMediaEvents(queued_media_events_);
|
||||
+
|
||||
+ queued_media_events_.clear();
|
||||
}
|
||||
|
||||
void BatchingMediaLog::SetTickClockForTesting(
|
||||
diff --git a/content/renderer/media/batching_media_log.h b/content/renderer/media/batching_media_log.h
|
||||
index 5810efdf0a75b809b94fb5abcd5f3dfbde7b019d..c59dbf2a2b980a89b41c45818476c77e9096339b 100644
|
||||
--- a/content/renderer/media/batching_media_log.h
|
||||
+++ b/content/renderer/media/batching_media_log.h
|
||||
@@ -63,9 +63,6 @@ class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
|
||||
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
- // impl for sending queued events.
|
||||
- std::vector<std::unique_ptr<EventHandler>> event_handlers_;
|
||||
-
|
||||
// |lock_| protects access to all of the following member variables. It
|
||||
// allows any render process thread to AddEvent(), while preserving their
|
||||
// sequence for throttled send on |task_runner_| and coherent retrieval by
|
||||
@@ -73,19 +70,24 @@ class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
|
||||
// guarantees provided by MediaLog, since SendQueuedMediaEvents must also
|
||||
// be synchronized with respect to AddEvent.
|
||||
mutable base::Lock lock_;
|
||||
- const base::TickClock* tick_clock_;
|
||||
- base::TimeTicks last_ipc_send_time_;
|
||||
- std::vector<media::MediaLogRecord> queued_media_events_;
|
||||
+ const base::TickClock* tick_clock_ GUARDED_BY(lock_);
|
||||
+ base::TimeTicks last_ipc_send_time_ GUARDED_BY(lock_);
|
||||
+ std::vector<media::MediaLogRecord> queued_media_events_ GUARDED_BY(lock_);
|
||||
+
|
||||
+ // impl for sending queued events.
|
||||
+ std::vector<std::unique_ptr<EventHandler>> event_handlers_ GUARDED_BY(lock_);
|
||||
|
||||
// For enforcing max 1 pending send.
|
||||
- bool ipc_send_pending_;
|
||||
+ bool ipc_send_pending_ GUARDED_BY(lock_);
|
||||
|
||||
// True if we've logged a warning message about exceeding rate limits.
|
||||
- bool logged_rate_limit_warning_;
|
||||
+ bool logged_rate_limit_warning_ GUARDED_BY(lock_);
|
||||
|
||||
// Limits the number of events we send over IPC to one.
|
||||
- absl::optional<media::MediaLogRecord> last_duration_changed_event_;
|
||||
- absl::optional<media::MediaLogRecord> last_buffering_state_event_;
|
||||
+ absl::optional<media::MediaLogRecord> last_duration_changed_event_
|
||||
+ GUARDED_BY(lock_);
|
||||
+ absl::optional<media::MediaLogRecord> last_buffering_state_event_
|
||||
+ GUARDED_BY(lock_);
|
||||
|
||||
// Holds the earliest MEDIA_ERROR_LOG_ENTRY event added to this log. This is
|
||||
// most likely to contain the most specific information available describing
|
||||
765
patches/chromium/cherry-pick-6bb320d134b1.patch
Normal file
765
patches/chromium/cherry-pick-6bb320d134b1.patch
Normal file
@@ -0,0 +1,765 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Costan <pwnall@chromium.org>
|
||||
Date: Thu, 11 Nov 2021 00:22:30 +0000
|
||||
Subject: M96: Storage Foundation: Share FileState ownership with I/O threads.
|
||||
|
||||
blink::NativeIOFile methods implementing the Storage Foundation
|
||||
JavaScript API pass raw pointers to NativeIOFile::FileState instances to
|
||||
their corresponding blink::NativeIOFile::Do*() methods, which rely on
|
||||
that CrossThreadPersistent<NativeIOFile> arguments to keep the
|
||||
underlying NativeIOFile::FileState instances alive.
|
||||
|
||||
CrossThreadPersistent can be used across threads to keep a garbage
|
||||
collected object alive, together with any non-garbage-collected objects
|
||||
that it owns. However, relying on CrossThreadPersistent existence to
|
||||
access the owned objects on a different thread is not safe.
|
||||
cppgc::subtle::CrossThreadPersistent (blink::CrossThreadPersistent is an
|
||||
alias to that) has comments explaining that the garbage collected heap
|
||||
can go away while the CrossThreadPersistent instance exists.
|
||||
|
||||
This CL fixes the problem by having the ownership of
|
||||
NativeIOFile::FileState be shared between the corresponding NativeIOFile
|
||||
instance and any threads doing I/O on the FileState.
|
||||
|
||||
(cherry picked from commit 7dc02206707362f3f92cea93f8eb2fa4af0d375f)
|
||||
|
||||
Bug: 1240593
|
||||
Change-Id: I5c9c818bcb23316fe1fd5afa57ed9c3fdb034377
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3269947
|
||||
Commit-Queue: Victor Costan <pwnall@chromium.org>
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940130}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3272672
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#945}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.cc b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
index 4d5aa4efa13930aea4886bac0fd8ba892ce8b5a5..615c1d3a20cba732a3d981bf6b2df181e56d2727 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "base/check.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/location.h"
|
||||
+#include "base/memory/scoped_refptr.h"
|
||||
#include "base/numerics/checked_math.h"
|
||||
#include "base/sequenced_task_runner.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
@@ -47,31 +48,167 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
-struct NativeIOFile::FileState {
|
||||
- explicit FileState(base::File file) : file(std::move(file)) {}
|
||||
+// State and logic for performing file I/O off the JavaScript thread.
|
||||
+//
|
||||
+// Instances are allocated on the PartitionAlloc heap. Instances cannot be
|
||||
+// garbage-collected, because garbage collected heaps get deallocated when the
|
||||
+// underlying threads are terminated, and we need a guarantee that each
|
||||
+// instance remains alive while it is used by a thread performing file I/O.
|
||||
+//
|
||||
+// Instances are initially constructed on a Blink thread that executes
|
||||
+// JavaScript, which can be Blink's main thread, or a worker thread. Afterwards,
|
||||
+// instances are (mostly*) only accessed on dedicated threads that do blocking
|
||||
+// file I/O.
|
||||
+//
|
||||
+// Mostly*: On macOS < 10.15, SetLength() synchronously accesses FileState on
|
||||
+// the JavaScript thread. This could be fixed with extra thread hopping. We're
|
||||
+// not currently planning to invest in the fix.
|
||||
+class NativeIOFile::FileState
|
||||
+ : public base::RefCountedThreadSafe<NativeIOFile::FileState> {
|
||||
+ public:
|
||||
+ explicit FileState(base::File file) : file_(std::move(file)) {
|
||||
+ DCHECK(file_.IsValid());
|
||||
+ }
|
||||
|
||||
FileState(const FileState&) = delete;
|
||||
FileState& operator=(const FileState&) = delete;
|
||||
|
||||
~FileState() = default;
|
||||
|
||||
+ // Returns true until Close() is called. Returns false afterwards.
|
||||
+ //
|
||||
+ // On macOS < 10.15, returns false between a TakeFile() call and the
|
||||
+ // corresponding SetFile() call.
|
||||
+ bool IsValid() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ return file_.IsValid();
|
||||
+ }
|
||||
+
|
||||
+ void Close() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ file_.Close();
|
||||
+ }
|
||||
+
|
||||
+ // Returns {length, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {invalid number, error} in case of failure.
|
||||
+ std::pair<int64_t, base::File::Error> GetLength() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int64_t length = file_.GetLength();
|
||||
+ base::File::Error error =
|
||||
+ (length < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+
|
||||
+ return {length, error};
|
||||
+ }
|
||||
+
|
||||
+ // Returns {expected_length, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {actual file length, error} in case of failure.
|
||||
+ std::pair<int64_t, base::File::Error> SetLength(int64_t expected_length) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK_GE(expected_length, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ bool success = file_.SetLength(expected_length);
|
||||
+ base::File::Error error =
|
||||
+ success ? base::File::FILE_OK : file_.GetLastFileError();
|
||||
+ int64_t actual_length = success ? expected_length : file_.GetLength();
|
||||
+
|
||||
+ return {actual_length, error};
|
||||
+ }
|
||||
+
|
||||
+#if defined(OS_MAC)
|
||||
+ // Used to implement browser-side SetLength() on macOS < 10.15.
|
||||
+ base::File TakeFile() {
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ return std::move(file_);
|
||||
+ }
|
||||
+
|
||||
+ // Used to implement browser-side SetLength() on macOS < 10.15.
|
||||
+ void SetFile(base::File file) {
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ DCHECK(!file_.IsValid()) << __func__ << " called on valid file";
|
||||
+
|
||||
+ file_ = std::move(file);
|
||||
+ }
|
||||
+#endif // defined(OS_MAC)
|
||||
+
|
||||
+ // Returns {read byte count, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {invalid number, error} in case of failure.
|
||||
+ std::pair<int, base::File::Error> Read(NativeIODataBuffer* buffer,
|
||||
+ int64_t file_offset,
|
||||
+ int read_size) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK(buffer);
|
||||
+ DCHECK_GE(file_offset, 0);
|
||||
+ DCHECK_GE(read_size, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int read_bytes = file_.Read(file_offset, buffer->Data(), read_size);
|
||||
+ base::File::Error error =
|
||||
+ (read_bytes < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+
|
||||
+ return {read_bytes, error};
|
||||
+ }
|
||||
+
|
||||
+ // Returns {0, write_size, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {actual file length, written bytes, base::File::OK} in case of a
|
||||
+ // short write.
|
||||
+ // Returns {actual file length, invalid number, error} in case of failure.
|
||||
+ std::tuple<int64_t, int, base::File::Error> Write(NativeIODataBuffer* buffer,
|
||||
+ int64_t file_offset,
|
||||
+ int write_size) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK(buffer);
|
||||
+ DCHECK_GE(file_offset, 0);
|
||||
+ DCHECK_GE(write_size, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int written_bytes = file_.Write(file_offset, buffer->Data(), write_size);
|
||||
+ base::File::Error error =
|
||||
+ (written_bytes < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+ int64_t actual_file_length_on_failure = 0;
|
||||
+ if (written_bytes < write_size || error != base::File::FILE_OK) {
|
||||
+ actual_file_length_on_failure = file_.GetLength();
|
||||
+ if (actual_file_length_on_failure < 0 && error != base::File::FILE_OK)
|
||||
+ error = file_.GetLastFileError();
|
||||
+ }
|
||||
+
|
||||
+ return {actual_file_length_on_failure, written_bytes, error};
|
||||
+ }
|
||||
+
|
||||
+ base::File::Error Flush() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ bool success = file_.Flush();
|
||||
+ return success ? base::File::FILE_OK : file_.GetLastFileError();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
// Lock coordinating cross-thread access to the state.
|
||||
- WTF::Mutex mutex;
|
||||
+ WTF::Mutex mutex_;
|
||||
+
|
||||
// The file on disk backing this NativeIOFile.
|
||||
- //
|
||||
- // The mutex is there to protect us against using the file after it was
|
||||
- // closed, and against OS-specific behavior around concurrent file access. It
|
||||
- // should never cause the main (JS) thread to block. This is because the mutex
|
||||
- // is only taken on the main thread in CloseBackingFile(), which is called
|
||||
- // when the NativeIOFile is destroyed (which implies there's no pending I/O
|
||||
- // operation, because all I/O operations hold onto a Persistent<NativeIOFile>)
|
||||
- // and when the mojo pipe is closed, which currently only happens when the JS
|
||||
- // context is being torn down.
|
||||
- //
|
||||
- // TODO(rstz): Is it possible and worthwhile to remove the mutex and rely
|
||||
- // exclusively on |NativeIOFile::io_pending_|, or remove
|
||||
- // |NativeIOFile::io_pending_| in favor of the mutex (might be harder)?
|
||||
- base::File file GUARDED_BY(mutex);
|
||||
+ base::File file_ GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
NativeIOFile::NativeIOFile(
|
||||
@@ -81,7 +218,7 @@ NativeIOFile::NativeIOFile(
|
||||
NativeIOCapacityTracker* capacity_tracker,
|
||||
ExecutionContext* execution_context)
|
||||
: file_length_(backing_file_length),
|
||||
- file_state_(std::make_unique<FileState>(std::move(backing_file))),
|
||||
+ file_state_(base::MakeRefCounted<FileState>(std::move(backing_file))),
|
||||
// TODO(pwnall): Get a dedicated queue when the specification matures.
|
||||
resolver_task_runner_(
|
||||
execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)),
|
||||
@@ -94,7 +231,7 @@ NativeIOFile::NativeIOFile(
|
||||
}
|
||||
|
||||
NativeIOFile::~NativeIOFile() {
|
||||
- // Needed to avoid having the base::File destructor close the file descriptor
|
||||
+ // Needed to avoid having the FileState destructor close the file descriptor
|
||||
// synchronously on the main thread.
|
||||
CloseBackingFile();
|
||||
}
|
||||
@@ -114,6 +251,9 @@ ScriptPromise NativeIOFile::close(ScriptState* script_state) {
|
||||
queued_close_resolver_ = resolver;
|
||||
|
||||
if (!io_pending_) {
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
+
|
||||
// Pretend that a close() promise was queued behind an I/O operation, and
|
||||
// the operation just finished. This is less logic than handling the
|
||||
// non-queued case separately.
|
||||
@@ -138,18 +278,15 @@ ScriptPromise NativeIOFile::getLength(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
- io_pending_ = true;
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoGetLength, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -175,6 +312,9 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
+
|
||||
int64_t expected_length = base::as_signed(new_length);
|
||||
|
||||
DCHECK_GE(expected_length, 0);
|
||||
@@ -201,8 +341,8 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
}
|
||||
file_length_ = expected_length;
|
||||
}
|
||||
- io_pending_ = true;
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
|
||||
#if defined(OS_MAC)
|
||||
@@ -217,26 +357,19 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
// To preserve this invariant, we pass this file's handle to the browser
|
||||
// process during the SetLength() mojo call, and the browser passes it back
|
||||
// when the call completes.
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state_->mutex);
|
||||
- backend_file_->SetLength(
|
||||
- expected_length, std::move(file_state_->file),
|
||||
- WTF::Bind(&NativeIOFile::DidSetLengthIpc, WrapPersistent(this),
|
||||
- WrapPersistent(resolver)));
|
||||
- }
|
||||
+ base::File file = file_state_->TakeFile();
|
||||
+ backend_file_->SetLength(
|
||||
+ expected_length, std::move(file),
|
||||
+ WTF::Bind(&NativeIOFile::DidSetLengthIpc, WrapPersistent(this),
|
||||
+ WrapPersistent(resolver)));
|
||||
return resolver->Promise();
|
||||
}
|
||||
#endif // defined(OS_MAC)
|
||||
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoSetLength, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, expected_length));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -258,6 +391,8 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
// TODO(pwnall): This assignment should move right before the
|
||||
// worker_pool::PostTask() call.
|
||||
@@ -281,16 +416,10 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // The first CrossThreadUnretained() is safe here because the
|
||||
- // NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
- // also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
- // FileState instance is guaranteed to remain alive during the task's
|
||||
- // execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoRead, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, std::move(result_buffer_data),
|
||||
file_offset, read_size));
|
||||
return resolver->Promise();
|
||||
@@ -313,6 +442,8 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
int write_size = NativeIOOperationSize(*buffer);
|
||||
int64_t write_end_offset;
|
||||
@@ -346,6 +477,14 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
file_length_ = write_end_offset;
|
||||
}
|
||||
|
||||
+ // TODO(pwnall): This assignment should move right before the
|
||||
+ // worker_pool::PostTask() call.
|
||||
+ //
|
||||
+ // `io_pending_` should only be set to true when we know for sure we'll post a
|
||||
+ // task that eventually results in getting `io_pending_` set back to false.
|
||||
+ // Having `io_pending_` set to true in an early return case (rejecting with an
|
||||
+ // exception) leaves the NativeIOFile "stuck" in a state where all future I/O
|
||||
+ // method calls will reject.
|
||||
io_pending_ = true;
|
||||
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
@@ -358,16 +497,10 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // The first CrossThreadUnretained() is safe here because the
|
||||
- // NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
- // also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
- // FileState instance is guaranteed to remain alive during the task's
|
||||
- // execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoWrite, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, std::move(result_buffer_data),
|
||||
file_offset, write_size));
|
||||
return resolver->Promise();
|
||||
@@ -391,18 +524,15 @@ ScriptPromise NativeIOFile::flush(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
- io_pending_ = true;
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoFlush, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -430,28 +560,29 @@ void NativeIOFile::DispatchQueuedClose() {
|
||||
ScriptPromiseResolver* resolver = queued_close_resolver_;
|
||||
queued_close_resolver_ = nullptr;
|
||||
|
||||
+ scoped_refptr<FileState> file_state = std::move(file_state_);
|
||||
+ DCHECK(!file_state_);
|
||||
+
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoClose, WrapCrossThreadPersistent(this),
|
||||
WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
- resolver_task_runner_));
|
||||
+ std::move(file_state), resolver_task_runner_));
|
||||
}
|
||||
|
||||
// static
|
||||
void NativeIOFile::DoClose(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- file_state->file.Close();
|
||||
- }
|
||||
+ file_state->Close();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -482,19 +613,17 @@ void NativeIOFile::DidClose(
|
||||
void NativeIOFile::DoGetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+
|
||||
+ int64_t length;
|
||||
base::File::Error get_length_error;
|
||||
- int64_t length = -1;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- length = file_state->file.GetLength();
|
||||
- get_length_error = (length < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- }
|
||||
+ std::tie(length, get_length_error) = file_state->GetLength();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -541,22 +670,20 @@ void NativeIOFile::DidGetLength(
|
||||
void NativeIOFile::DoSetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
int64_t expected_length) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK_GE(expected_length, 0);
|
||||
|
||||
- base::File::Error set_length_error;
|
||||
int64_t actual_length;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- bool success = file_state->file.SetLength(expected_length);
|
||||
- set_length_error =
|
||||
- success ? base::File::FILE_OK : file_state->file.GetLastFileError();
|
||||
- actual_length = success ? expected_length : file_state->file.GetLength();
|
||||
- }
|
||||
+ base::File::Error set_length_error;
|
||||
+ std::tie(actual_length, set_length_error) =
|
||||
+ file_state->SetLength(expected_length);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -619,10 +746,7 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
int64_t actual_length,
|
||||
mojom::blink::NativeIOErrorPtr set_length_error) {
|
||||
DCHECK(backing_file.IsValid()) << "browser returned closed file";
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state_->mutex);
|
||||
- file_state_->file = std::move(backing_file);
|
||||
- }
|
||||
+ file_state_->SetFile(std::move(backing_file));
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
|
||||
DCHECK(io_pending_) << "I/O operation performed without io_pending_ set";
|
||||
@@ -673,13 +797,15 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
void NativeIOFile::DoRead(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
-
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
DCHECK(resolver_task_runner);
|
||||
DCHECK(result_buffer_data);
|
||||
DCHECK(result_buffer_data->IsValid());
|
||||
@@ -690,15 +816,8 @@ void NativeIOFile::DoRead(
|
||||
|
||||
int read_bytes;
|
||||
base::File::Error read_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- read_bytes = file_state->file.Read(file_offset, result_buffer_data->Data(),
|
||||
- read_size);
|
||||
- read_error = (read_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- }
|
||||
+ std::tie(read_bytes, read_error) =
|
||||
+ file_state->Read(result_buffer_data.get(), file_offset, read_size);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -743,12 +862,15 @@ void NativeIOFile::DidRead(
|
||||
void NativeIOFile::DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
DCHECK(resolver_task_runner);
|
||||
DCHECK(result_buffer_data);
|
||||
DCHECK(result_buffer_data->IsValid());
|
||||
@@ -760,22 +882,8 @@ void NativeIOFile::DoWrite(
|
||||
int written_bytes;
|
||||
int64_t actual_file_length_on_failure = 0;
|
||||
base::File::Error write_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- written_bytes = file_state->file.Write(
|
||||
- file_offset, result_buffer_data->Data(), write_size);
|
||||
- write_error = (written_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- if (written_bytes < write_size || write_error != base::File::FILE_OK) {
|
||||
- actual_file_length_on_failure = file_state->file.GetLength();
|
||||
- if (actual_file_length_on_failure < 0 &&
|
||||
- write_error != base::File::FILE_OK) {
|
||||
- write_error = file_state->file.GetLastFileError();
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ std::tie(actual_file_length_on_failure, written_bytes, write_error) =
|
||||
+ file_state->Write(result_buffer_data.get(), file_offset, write_size);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -846,18 +954,14 @@ void NativeIOFile::DidWrite(
|
||||
void NativeIOFile::DoFlush(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
- base::File::Error flush_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- bool success = file_state->file.Flush();
|
||||
- flush_error =
|
||||
- success ? base::File::FILE_OK : file_state->file.GetLastFileError();
|
||||
- }
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+
|
||||
+ base::File::Error flush_error = file_state->Flush();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -887,20 +991,23 @@ void NativeIOFile::DidFlush(
|
||||
|
||||
void NativeIOFile::CloseBackingFile() {
|
||||
closed_ = true;
|
||||
- file_state_->mutex.lock();
|
||||
- base::File backing_file = std::move(file_state_->file);
|
||||
- file_state_->mutex.unlock();
|
||||
|
||||
- if (!backing_file.IsValid()) {
|
||||
+ if (!file_state_) {
|
||||
// Avoid posting a cross-thread task if the file is already closed. This is
|
||||
// the expected path.
|
||||
return;
|
||||
}
|
||||
|
||||
- worker_pool::PostTask(
|
||||
- FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce([](base::File file) { file.Close(); },
|
||||
- std::move(backing_file)));
|
||||
+ scoped_refptr<FileState> file_state = std::move(file_state_);
|
||||
+ DCHECK(!file_state_);
|
||||
+
|
||||
+ worker_pool::PostTask(FROM_HERE, {base::MayBlock()},
|
||||
+ CrossThreadBindOnce(
|
||||
+ [](scoped_refptr<FileState> file_state) {
|
||||
+ DCHECK(file_state);
|
||||
+ file_state->Close();
|
||||
+ },
|
||||
+ std::move(file_state)));
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.h b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
index 8ae49ebc2d36d547d152d4e56192e30f8cacd641..95d2da4ac3e1859a0abc21ea15d269758eed1681 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
@@ -67,12 +67,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
void Trace(Visitor* visitor) const override;
|
||||
|
||||
private:
|
||||
- // Data accessed on the threads that do file I/O.
|
||||
- //
|
||||
- // Instances are allocated on the PartitionAlloc heap. Instances are initially
|
||||
- // constructed on Blink's main thread, or on a worker thread. Afterwards,
|
||||
- // instances are only accessed on dedicated threads that do blocking file I/O.
|
||||
- struct FileState;
|
||||
+ class FileState;
|
||||
|
||||
// Called when the mojo backend disconnects.
|
||||
void OnBackendDisconnect();
|
||||
@@ -84,7 +79,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoClose(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file I/O part of close(), on the main thread.
|
||||
void DidClose(CrossThreadPersistent<ScriptPromiseResolver> resolver);
|
||||
@@ -93,7 +88,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoGetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file I/O part of getLength(), on the main thread.
|
||||
void DidGetLength(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
@@ -104,7 +99,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoSetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
int64_t expected_length);
|
||||
// Performs the post file I/O part of setLength(), on the main thread.
|
||||
@@ -128,7 +123,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// Performs the file I/O part of read(), off the main thread.
|
||||
static void DoRead(CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
@@ -143,7 +138,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
@@ -163,7 +158,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoFlush(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file-I/O part of flush(), on the main thread.
|
||||
void DidFlush(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
@@ -210,8 +205,13 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// TODO(rstz): Consider moving this variable into `file_state_`
|
||||
int64_t file_length_ = 0;
|
||||
|
||||
- // See NativeIOFile::FileState, declared above.
|
||||
- const std::unique_ptr<FileState> file_state_;
|
||||
+ // Points to a NativeIOFile::FileState while the underlying file is open.
|
||||
+ //
|
||||
+ // When the underlying file is closed, this pointer is nulled out, and the
|
||||
+ // FileState instance is passed to a different thread, where the closing
|
||||
+ // happens. This avoids having any I/O performed by the base::File::Close()
|
||||
+ // jank the JavaScript thread that owns this NativeIOFile instance.
|
||||
+ scoped_refptr<FileState> file_state_;
|
||||
|
||||
// Schedules resolving Promises with file I/O results.
|
||||
const scoped_refptr<base::SequencedTaskRunner> resolver_task_runner_;
|
||||
151
patches/chromium/cherry-pick-9db9911e1242.patch
Normal file
151
patches/chromium/cherry-pick-9db9911e1242.patch
Normal file
@@ -0,0 +1,151 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Stephen Roettger <sroettger@google.com>
|
||||
Date: Fri, 7 Jan 2022 09:36:31 +0000
|
||||
Subject: Keep a set of previously dropped peers
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Test that a given node name hasn't been seen before.
|
||||
A side effect of this fix is that re-invitation will not work anymore.
|
||||
|
||||
BUG=chromium:1274113
|
||||
|
||||
Change-Id: Ibdc50291efa1f6298614b163b544ad980615a981
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3341553
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Stephen Röttger <sroettger@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#956441}
|
||||
|
||||
diff --git a/mojo/core/invitation_unittest.cc b/mojo/core/invitation_unittest.cc
|
||||
index 2c8eeef9feefc6be689f1ca2052af316b4b7db68..0687a58ee2b294580d1165e872ec5855e5de2b53 100644
|
||||
--- a/mojo/core/invitation_unittest.cc
|
||||
+++ b/mojo/core/invitation_unittest.cc
|
||||
@@ -693,7 +693,8 @@ DEFINE_TEST_CLIENT(ProcessErrorsClient) {
|
||||
EXPECT_EQ(kDisconnectMessage, ReadMessage(pipe));
|
||||
}
|
||||
|
||||
-TEST_F(InvitationTest, Reinvitation) {
|
||||
+// Temporary removed support for reinvitation for non-isolated connections.
|
||||
+TEST_F(InvitationTest, DISABLED_Reinvitation) {
|
||||
// The gist of this test is that a process should be able to accept an
|
||||
// invitation, lose its connection to the process network, and then accept a
|
||||
// new invitation to re-establish communication.
|
||||
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
|
||||
index 21edab39368e69ee6665e490b2c4de13f424edbd..79b933ebbe9eb1cb9eb11512f8480c682811745c 100644
|
||||
--- a/mojo/core/node_controller.cc
|
||||
+++ b/mojo/core/node_controller.cc
|
||||
@@ -543,7 +543,8 @@ scoped_refptr<NodeChannel> NodeController::GetBrokerChannel() {
|
||||
|
||||
void NodeController::AddPeer(const ports::NodeName& name,
|
||||
scoped_refptr<NodeChannel> channel,
|
||||
- bool start_channel) {
|
||||
+ bool start_channel,
|
||||
+ bool allow_name_reuse) {
|
||||
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
DCHECK(name != ports::kInvalidNodeName);
|
||||
@@ -562,6 +563,11 @@ void NodeController::AddPeer(const ports::NodeName& name,
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (dropped_peers_.Contains(name) && !allow_name_reuse) {
|
||||
+ LOG(ERROR) << "Trying to re-add dropped peer " << name;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
auto result = peers_.insert(std::make_pair(name, channel));
|
||||
DCHECK(result.second);
|
||||
|
||||
@@ -602,6 +608,7 @@ void NodeController::DropPeer(const ports::NodeName& node_name,
|
||||
if (it != peers_.end()) {
|
||||
ports::NodeName peer = it->first;
|
||||
peers_.erase(it);
|
||||
+ dropped_peers_.Insert(peer);
|
||||
DVLOG(1) << "Dropped peer " << peer;
|
||||
}
|
||||
|
||||
@@ -1265,7 +1272,8 @@ void NodeController::OnAcceptPeer(const ports::NodeName& from_node,
|
||||
// Note that we explicitly drop any prior connection to the same peer so
|
||||
// that new isolated connections can replace old ones.
|
||||
DropPeer(peer_name, nullptr);
|
||||
- AddPeer(peer_name, channel, false /* start_channel */);
|
||||
+ AddPeer(peer_name, channel, false /* start_channel */,
|
||||
+ true /* allow_name_reuse */);
|
||||
DVLOG(1) << "Node " << name_ << " accepted peer " << peer_name;
|
||||
}
|
||||
|
||||
@@ -1381,5 +1389,24 @@ NodeController::IsolatedConnection&
|
||||
NodeController::IsolatedConnection::operator=(IsolatedConnection&& other) =
|
||||
default;
|
||||
|
||||
+BoundedPeerSet::BoundedPeerSet() = default;
|
||||
+BoundedPeerSet::~BoundedPeerSet() = default;
|
||||
+
|
||||
+void BoundedPeerSet::Insert(const ports::NodeName& name) {
|
||||
+ if (new_set_.size() == kHalfSize) {
|
||||
+ old_set_.clear();
|
||||
+ std::swap(old_set_, new_set_);
|
||||
+ }
|
||||
+ new_set_.insert(name);
|
||||
+}
|
||||
+
|
||||
+bool BoundedPeerSet::Contains(const ports::NodeName& name) {
|
||||
+ if (old_set_.find(name) != old_set_.end())
|
||||
+ return true;
|
||||
+ if (new_set_.find(name) != new_set_.end())
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
} // namespace core
|
||||
} // namespace mojo
|
||||
diff --git a/mojo/core/node_controller.h b/mojo/core/node_controller.h
|
||||
index 040eeab79f72efcdb2823cf62e7dbaefa8b9233f..571e578da4950135456bb97c8ea7a30ceabca7cc 100644
|
||||
--- a/mojo/core/node_controller.h
|
||||
+++ b/mojo/core/node_controller.h
|
||||
@@ -38,6 +38,26 @@ namespace core {
|
||||
class Broker;
|
||||
class Core;
|
||||
|
||||
+// A set of NodeNames that is bounded by a maximum size.
|
||||
+// If the max size is reached, it will delete the older half of stored names.
|
||||
+class BoundedPeerSet {
|
||||
+ public:
|
||||
+ BoundedPeerSet();
|
||||
+ BoundedPeerSet(const BoundedPeerSet&) = delete;
|
||||
+ BoundedPeerSet& operator=(const BoundedPeerSet&) = delete;
|
||||
+
|
||||
+ ~BoundedPeerSet();
|
||||
+
|
||||
+ void Insert(const ports::NodeName& name);
|
||||
+ bool Contains(const ports::NodeName& name);
|
||||
+
|
||||
+ private:
|
||||
+ static constexpr int kHalfSize = 50000;
|
||||
+
|
||||
+ std::unordered_set<ports::NodeName> old_set_;
|
||||
+ std::unordered_set<ports::NodeName> new_set_;
|
||||
+};
|
||||
+
|
||||
// The owner of ports::Node which facilitates core EDK implementation. All
|
||||
// public interface methods are safe to call from any thread.
|
||||
class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
@@ -180,7 +200,8 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
|
||||
void AddPeer(const ports::NodeName& name,
|
||||
scoped_refptr<NodeChannel> channel,
|
||||
- bool start_channel);
|
||||
+ bool start_channel,
|
||||
+ bool allow_name_reuse = false);
|
||||
void DropPeer(const ports::NodeName& name, NodeChannel* channel);
|
||||
void SendPeerEvent(const ports::NodeName& name, ports::ScopedEvent event);
|
||||
void DropAllPeers();
|
||||
@@ -265,6 +286,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
|
||||
// Channels to known peers, including inviter and invitees, if any.
|
||||
NodeMap peers_;
|
||||
+ BoundedPeerSet dropped_peers_;
|
||||
|
||||
// Outgoing message queues for peers we've heard of but can't yet talk to.
|
||||
std::unordered_map<ports::NodeName, OutgoingMessageQueue>
|
||||
41
patches/chromium/cherry-pick-be50c60b4225.patch
Normal file
41
patches/chromium/cherry-pick-be50c60b4225.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Wed, 2 Feb 2022 05:45:44 +0000
|
||||
Subject: Viz: Fix UAF on context loss
|
||||
|
||||
(cherry picked from commit 98d246cabe677e1d8287e4d42ce02825417be9e2)
|
||||
|
||||
Fixed: 1250655
|
||||
Change-Id: I2898316635d370fa36b94e0ae2564ed357745b2c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3413372
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Commit-Queue: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#963012}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3430523
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1050}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
index a31c10c610000415b5a88a0824eea63b45a435cc..1b323f142d934afea0215dea190efaa197cec554 100644
|
||||
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
@@ -478,9 +478,13 @@ const gpu::GpuFeatureInfo& ContextProviderCommandBuffer::GetGpuFeatureInfo()
|
||||
void ContextProviderCommandBuffer::OnLostContext() {
|
||||
CheckValidThreadOrLockAcquired();
|
||||
|
||||
- // Ensure |this| isn't destroyed in the middle of OnLostContext() if observers
|
||||
- // drop all references to it.
|
||||
- scoped_refptr<ContextProviderCommandBuffer> ref(this);
|
||||
+ // Observers may drop the last persistent references to `this`, but there may
|
||||
+ // be weak references in use further up the stack. This task is posted to
|
||||
+ // ensure that destruction is deferred until it's safe.
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce([](scoped_refptr<ContextProviderCommandBuffer>) {},
|
||||
+ base::WrapRefCounted(this)));
|
||||
|
||||
for (auto& observer : observers_)
|
||||
observer.OnContextLost();
|
||||
183
patches/chromium/cherry-pick-c5571653d932.patch
Normal file
183
patches/chromium/cherry-pick-c5571653d932.patch
Normal file
@@ -0,0 +1,183 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jarryd <jarrydg@chromium.org>
|
||||
Date: Wed, 29 Dec 2021 19:49:22 +0000
|
||||
Subject: Quota: Use Threadsafe Pressure Callback.
|
||||
|
||||
Fixes UAF by removing use of raw ptr to StorageNotificationService.
|
||||
Instead, the service's interface exposes a method to create a
|
||||
thread-safe callback to pass to the quota manager instead.
|
||||
|
||||
This change also changes the parameter type for the call chain from
|
||||
url::Origin to blink::StorageKey to match the type Quota is keyed on.
|
||||
|
||||
Bug:1275020
|
||||
|
||||
(cherry picked from commit e304c0373f9cc4a65d39d7094e4897627e83390e)
|
||||
|
||||
Change-Id: Icc696d22fa41324e7a6c056599db635bb5de6291
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3347939
|
||||
Reviewed-by: Joshua Bell <jsbell@chromium.org>
|
||||
Reviewed-by: Nasko Oskov <nasko@chromium.org>
|
||||
Commit-Queue: Jarryd Goodman <jarrydg@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#953375}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3360203
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Owners-Override: Krishna Govind <govind@chromium.org>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1352}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/storage/storage_notification_service_impl.cc b/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
index f8b38745827b25e46bfd1b4225bb3c55f2836d02..ceeafe0ad40e69574ccf885e4230ce042ecbaaaa 100644
|
||||
--- a/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
+++ b/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
+#include "content/public/browser/browser_task_traits.h"
|
||||
+#include "content/public/browser/browser_thread.h"
|
||||
|
||||
#if !defined(OS_ANDROID)
|
||||
#include "chrome/browser/ui/storage_pressure_bubble.h"
|
||||
@@ -36,8 +38,26 @@ const base::TimeDelta GetThrottlingInterval() {
|
||||
|
||||
} // namespace
|
||||
|
||||
+StoragePressureNotificationCallback
|
||||
+StorageNotificationServiceImpl::CreateThreadSafePressureNotificationCallback() {
|
||||
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
+ auto thread_unsafe_callback = base::BindRepeating(
|
||||
+ &StorageNotificationServiceImpl::MaybeShowStoragePressureNotification,
|
||||
+ weak_ptr_factory_.GetWeakPtr());
|
||||
+ return base::BindRepeating(
|
||||
+ [](StoragePressureNotificationCallback cb, blink::StorageKey key) {
|
||||
+ content::GetUIThreadTaskRunner({})->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce([](StoragePressureNotificationCallback callback,
|
||||
+ blink::StorageKey key) { callback.Run(key); },
|
||||
+ std::move(cb), key));
|
||||
+ },
|
||||
+ std::move(thread_unsafe_callback));
|
||||
+}
|
||||
+
|
||||
void StorageNotificationServiceImpl::MaybeShowStoragePressureNotification(
|
||||
- const url::Origin origin) {
|
||||
+ const blink::StorageKey storage_key) {
|
||||
+ auto origin = storage_key.origin();
|
||||
if (!disk_pressure_notification_last_sent_at_.is_null() &&
|
||||
base::TimeTicks::Now() - disk_pressure_notification_last_sent_at_ <
|
||||
GetThrottlingInterval()) {
|
||||
diff --git a/chrome/browser/storage/storage_notification_service_impl.h b/chrome/browser/storage/storage_notification_service_impl.h
|
||||
index 497a3063c835a37fe9141052263cf70c863235fa..44fe169b82ced5e328060f191d608aaa57d3af71 100644
|
||||
--- a/chrome/browser/storage/storage_notification_service_impl.h
|
||||
+++ b/chrome/browser/storage/storage_notification_service_impl.h
|
||||
@@ -5,10 +5,12 @@
|
||||
#ifndef CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
#define CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
|
||||
+#include "base/memory/weak_ptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "components/keyed_service/core/keyed_service.h"
|
||||
#include "content/public/browser/storage_notification_service.h"
|
||||
+#include "third_party/blink/public/common/storage_key/storage_key.h"
|
||||
|
||||
class StorageNotificationServiceImpl
|
||||
: public content::StorageNotificationService,
|
||||
@@ -16,13 +18,20 @@ class StorageNotificationServiceImpl
|
||||
public:
|
||||
StorageNotificationServiceImpl();
|
||||
~StorageNotificationServiceImpl() override;
|
||||
- void MaybeShowStoragePressureNotification(const url::Origin) override;
|
||||
+ // Called from the UI thread, this method returns a callback that can passed
|
||||
+ // to any thread, and proxies calls to
|
||||
+ // `MaybeShowStoragePressureNotification()` back to the UI thread. It wraps a
|
||||
+ // weak pointer to `this`.
|
||||
+ StoragePressureNotificationCallback
|
||||
+ CreateThreadSafePressureNotificationCallback() override;
|
||||
+ void MaybeShowStoragePressureNotification(const blink::StorageKey) override;
|
||||
base::TimeTicks GetLastSentAtForTesting() {
|
||||
return disk_pressure_notification_last_sent_at_;
|
||||
}
|
||||
|
||||
private:
|
||||
base::TimeTicks disk_pressure_notification_last_sent_at_;
|
||||
+ base::WeakPtrFactory<StorageNotificationServiceImpl> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index 86c6de60739a0c5aa49ed63f1546b478d7f58054..263fe6195ac6d48cd7a985ca844d1a6e421a9b1d 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1169,23 +1169,14 @@ void StoragePartitionImpl::Initialize(
|
||||
StorageNotificationService* storage_notification_service =
|
||||
browser_context_->GetStorageNotificationService();
|
||||
if (storage_notification_service) {
|
||||
- // base::Unretained is safe to use because the BrowserContext is guaranteed
|
||||
- // to outlive QuotaManager. This is because BrowserContext outlives this
|
||||
- // StoragePartitionImpl, which destroys the QuotaManager on teardown.
|
||||
- base::RepeatingCallback<void(const blink::StorageKey)>
|
||||
- send_notification_function = base::BindRepeating(
|
||||
- [](StorageNotificationService* service,
|
||||
- const blink::StorageKey storage_key) {
|
||||
- GetUIThreadTaskRunner({})->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&StorageNotificationService::
|
||||
- MaybeShowStoragePressureNotification,
|
||||
- base::Unretained(service),
|
||||
- std::move(storage_key.origin())));
|
||||
- },
|
||||
- base::Unretained(storage_notification_service));
|
||||
-
|
||||
- quota_manager_->SetStoragePressureCallback(send_notification_function);
|
||||
+ // The weak ptr associated with the pressure notification callback will be
|
||||
+ // created and evaluated by a task runner on the UI thread, as confirmed by
|
||||
+ // the DCHECK's above, ensuring that the task runner does not attempt to run
|
||||
+ // the callback in the case that the storage notification service is already
|
||||
+ // destructed.
|
||||
+ quota_manager_->SetStoragePressureCallback(
|
||||
+ storage_notification_service
|
||||
+ ->CreateThreadSafePressureNotificationCallback());
|
||||
}
|
||||
|
||||
// Each consumer is responsible for registering its QuotaClient during
|
||||
diff --git a/content/public/browser/storage_notification_service.h b/content/public/browser/storage_notification_service.h
|
||||
index 3eec5ef29051008041695bcf7ebbf63787f5bd89..e72adada318f1cb998e2a9e7468a6f2e54742760 100644
|
||||
--- a/content/public/browser/storage_notification_service.h
|
||||
+++ b/content/public/browser/storage_notification_service.h
|
||||
@@ -8,6 +8,15 @@
|
||||
#include "base/bind.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
+namespace blink {
|
||||
+class StorageKey;
|
||||
+}
|
||||
+
|
||||
+namespace {
|
||||
+using StoragePressureNotificationCallback =
|
||||
+ base::RepeatingCallback<void(const blink::StorageKey)>;
|
||||
+}
|
||||
+
|
||||
namespace content {
|
||||
|
||||
// This interface is used to create a connection between the storage layer and
|
||||
@@ -19,12 +28,15 @@ class StorageNotificationService {
|
||||
StorageNotificationService() = default;
|
||||
~StorageNotificationService() = default;
|
||||
|
||||
- // This pure virtual function should be implemented in the embedder layer
|
||||
+ // These pure virtual functions should be implemented in the embedder layer
|
||||
// where calls to UI and notification code can be implemented. This closure
|
||||
// is passed to QuotaManager in StoragePartitionImpl, where it is called
|
||||
// when QuotaManager determines appropriate to alert the user that the device
|
||||
// is in a state of storage pressure.
|
||||
- virtual void MaybeShowStoragePressureNotification(const url::Origin) = 0;
|
||||
+ virtual void MaybeShowStoragePressureNotification(
|
||||
+ const blink::StorageKey) = 0;
|
||||
+ virtual StoragePressureNotificationCallback
|
||||
+ CreateThreadSafePressureNotificationCallback() = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StorageNotificationService);
|
||||
62
patches/chromium/cherry-pick-da11d71a0227.patch
Normal file
62
patches/chromium/cherry-pick-da11d71a0227.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Fri, 10 Dec 2021 01:03:53 +0000
|
||||
Subject: mojo/ipc: Drop messages targeting invalid task runner
|
||||
|
||||
If the endpoint's task runner does not match the current task runner (or
|
||||
an equivalent main-thread task runner for the ChannelProxy) when a
|
||||
executing a message dispatch task for that endpoint, this ignores the
|
||||
message instead of dispatching it on the wrong sequence.
|
||||
|
||||
(cherry picked from commit 0747c9405e1098c0bbbc5593183696eafb45b72c)
|
||||
|
||||
Fixed: 1263457
|
||||
Change-Id: I4f6ba22de3ff8cf3994b748e1ffd0f0aabb17b70
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3318601
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#949140}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3328403
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1269}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
|
||||
index 18b4dc9be5bf54e6f5443d53739bc06ba3f98767..07e522337090494e278395ac4e7ead73c472ef72 100644
|
||||
--- a/ipc/ipc_mojo_bootstrap.cc
|
||||
+++ b/ipc/ipc_mojo_bootstrap.cc
|
||||
@@ -966,11 +966,14 @@ class ChannelAssociatedGroupController
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
+ if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
|
||||
+ !proxy_task_runner_->RunsTasksInCurrentSequence()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Using client->interface_name() is safe here because this is a static
|
||||
// string defined for each mojo interface.
|
||||
TRACE_EVENT0("mojom", client->interface_name());
|
||||
- DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence() ||
|
||||
- proxy_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
// Sync messages should never make their way to this method.
|
||||
DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
|
||||
@@ -1000,11 +1003,14 @@ class ChannelAssociatedGroupController
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
+ if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
|
||||
+ !proxy_task_runner_->RunsTasksInCurrentSequence()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Using client->interface_name() is safe here because this is a static
|
||||
// string defined for each mojo interface.
|
||||
TRACE_EVENT0("mojom", client->interface_name());
|
||||
- DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence() ||
|
||||
- proxy_task_runner_->RunsTasksInCurrentSequence());
|
||||
MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
|
||||
|
||||
// The message must have already been dequeued by the endpoint waking up
|
||||
308
patches/chromium/cherry-pick-dbde8795233a.patch
Normal file
308
patches/chromium/cherry-pick-dbde8795233a.patch
Normal file
@@ -0,0 +1,308 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Meenan <pmeenan@chromium.org>
|
||||
Date: Fri, 3 Dec 2021 18:15:17 +0000
|
||||
Subject: Prevent opaque range request responses from entering the preload
|
||||
cache
|
||||
|
||||
ResourceLoader cancels range request responses that were not initiated
|
||||
with range request headers causing them to error out and be cleared from
|
||||
the preload cache. Other responses (200, 416, error, etc) complete
|
||||
successfully and would otherwise enter the preload cache, making them
|
||||
observable.
|
||||
|
||||
This prevents opaque range responses of any kind from persisting in the
|
||||
preload cache (which would not naturally have any anyway).
|
||||
|
||||
(cherry picked from commit a5f630e5f94da28a926d60da7dde194acd8697f0)
|
||||
|
||||
Bug: 1270990
|
||||
Change-Id: Ife9922fe0b88e39722f3664ddd091a1516892157
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3294001
|
||||
Reviewed-by: Ben Kelly <wanderview@chromium.org>
|
||||
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
|
||||
Commit-Queue: Patrick Meenan <pmeenan@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#946055}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3313416
|
||||
Auto-Submit: Patrick Meenan <pmeenan@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1222}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
index 8fc72ba0b932bd20b96630373e3bc4ee7765c8a1..d27c52259038fe5daf23f9ad0acbf7cb1ade38fb 100644
|
||||
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
@@ -1873,6 +1873,19 @@ void ResourceFetcher::HandleLoaderFinish(Resource* resource,
|
||||
}
|
||||
|
||||
resource->VirtualTimePauser().UnpauseVirtualTime();
|
||||
+
|
||||
+ // A response should not serve partial content if it was not requested via a
|
||||
+ // Range header: https://fetch.spec.whatwg.org/#main-fetch so keep it out
|
||||
+ // of the preload cache in case of a non-206 response (which generates an
|
||||
+ // error).
|
||||
+ if (resource->GetResponse().GetType() ==
|
||||
+ network::mojom::FetchResponseType::kOpaque &&
|
||||
+ resource->GetResponse().HasRangeRequested() &&
|
||||
+ !resource->GetResourceRequest().HttpHeaderFields().Contains(
|
||||
+ net::HttpRequestHeaders::kRange)) {
|
||||
+ RemovePreload(resource);
|
||||
+ }
|
||||
+
|
||||
if (type == kDidFinishLoading) {
|
||||
resource->Finish(response_end, freezable_task_runner_.get());
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a0058551d52d45b3c16882014be740d75e51ddd1
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
|
||||
@@ -0,0 +1,47 @@
|
||||
+"""
|
||||
+This generates a partial response for a 100-byte text file.
|
||||
+"""
|
||||
+import re
|
||||
+
|
||||
+from wptserve.utils import isomorphic_decode
|
||||
+
|
||||
+def main(request, response):
|
||||
+ total_length = int(request.GET.first(b'length', b'100'))
|
||||
+ partial_code = int(request.GET.first(b'partial', b'206'))
|
||||
+ range_header = request.headers.get(b'Range', b'')
|
||||
+
|
||||
+ # Send a 200 if there is no range request
|
||||
+ if not range_header:
|
||||
+ to_send = ''.zfill(total_length)
|
||||
+ response.headers.set(b"Content-Type", b"text/plain")
|
||||
+ response.headers.set(b"Cache-Control", b"no-cache")
|
||||
+ response.headers.set(b"Content-Length", total_length)
|
||||
+ response.content = to_send
|
||||
+ return
|
||||
+
|
||||
+ # Simple range parsing, requires specifically "bytes=xxx-xxxx"
|
||||
+ range_header_match = re.search(r'^bytes=(\d*)-(\d*)$', isomorphic_decode(range_header))
|
||||
+ start, end = range_header_match.groups()
|
||||
+ start = int(start)
|
||||
+ end = int(end) if end else total_length
|
||||
+ length = end - start
|
||||
+
|
||||
+ # Error the request if the range goes beyond the length
|
||||
+ if length <= 0 or end > total_length:
|
||||
+ response.set_error(416, u"Range Not Satisfiable")
|
||||
+ response.write()
|
||||
+ return
|
||||
+
|
||||
+ # Generate a partial response of the requested length
|
||||
+ to_send = ''.zfill(length)
|
||||
+ response.headers.set(b"Content-Type", b"text/plain")
|
||||
+ response.headers.set(b"Accept-Ranges", b"bytes")
|
||||
+ response.headers.set(b"Cache-Control", b"no-cache")
|
||||
+ response.status = partial_code
|
||||
+
|
||||
+ content_range = b"bytes %d-%d/%d" % (start, end, total_length)
|
||||
+
|
||||
+ response.headers.set(b"Content-Range", content_range)
|
||||
+ response.headers.set(b"Content-Length", length)
|
||||
+
|
||||
+ response.content = to_send
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
index 3680c0c471d3d5f36c4aba4cc58dcd52c38a08df..b47823f03b4ef3749e622fbf7dd3b515a216b5be 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
@@ -12,7 +12,7 @@ async function broadcast(msg) {
|
||||
}
|
||||
}
|
||||
|
||||
-addEventListener('fetch', event => {
|
||||
+addEventListener('fetch', async event => {
|
||||
/** @type Request */
|
||||
const request = event.request;
|
||||
const url = new URL(request.url);
|
||||
@@ -34,6 +34,11 @@ addEventListener('fetch', event => {
|
||||
case 'broadcast-accept-encoding':
|
||||
broadcastAcceptEncoding(event);
|
||||
return;
|
||||
+ case 'record-media-range-request':
|
||||
+ return recordMediaRangeRequest(event);
|
||||
+ case 'use-media-range-request':
|
||||
+ useMediaRangeRequest(event);
|
||||
+ return;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -157,3 +162,57 @@ function broadcastAcceptEncoding(event) {
|
||||
// Just send back any response, it isn't important for the test.
|
||||
event.respondWith(new Response(''));
|
||||
}
|
||||
+
|
||||
+let rangeResponse = {};
|
||||
+
|
||||
+async function recordMediaRangeRequest(event) {
|
||||
+ /** @type Request */
|
||||
+ const request = event.request;
|
||||
+ const url = new URL(request.url);
|
||||
+ const urlParams = new URLSearchParams(url.search);
|
||||
+ const size = urlParams.get("size");
|
||||
+ const id = urlParams.get('id');
|
||||
+ const key = 'size' + size;
|
||||
+
|
||||
+ if (key in rangeResponse) {
|
||||
+ // Don't re-fetch ranges we already have.
|
||||
+ const clonedResponse = rangeResponse[key].clone();
|
||||
+ event.respondWith(clonedResponse);
|
||||
+ } else if (event.request.headers.get("range") === "bytes=0-") {
|
||||
+ // Generate a bogus 206 response to trigger subsequent range requests
|
||||
+ // of the desired size.
|
||||
+ const length = urlParams.get("length") + 100;
|
||||
+ const body = "A".repeat(Number(size));
|
||||
+ event.respondWith(new Response(body, {status: 206, headers: {
|
||||
+ "Content-Type": "audio/mp4",
|
||||
+ "Content-Range": `bytes 0-1/${length}`
|
||||
+ }}));
|
||||
+ } else if (event.request.headers.get("range") === `bytes=${Number(size)}-`) {
|
||||
+ // Pass through actual range requests which will attempt to fetch up to the
|
||||
+ // length in the original response which is bigger than the actual resource
|
||||
+ // to make sure 206 and 416 responses are treated the same.
|
||||
+ rangeResponse[key] = await fetch(event.request);
|
||||
+
|
||||
+ // Let the client know we have the range response for the given ID
|
||||
+ broadcast({id});
|
||||
+ } else {
|
||||
+ event.respondWith(Promise.reject(Error("Invalid Request")));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+function useMediaRangeRequest(event) {
|
||||
+ /** @type Request */
|
||||
+ const request = event.request;
|
||||
+ const url = new URL(request.url);
|
||||
+ const urlParams = new URLSearchParams(url.search);
|
||||
+ const size = urlParams.get("size");
|
||||
+ const key = 'size' + size;
|
||||
+
|
||||
+ // Send a clone of the range response to preload.
|
||||
+ if (key in rangeResponse) {
|
||||
+ const clonedResponse = rangeResponse[key].clone();
|
||||
+ event.respondWith(clonedResponse);
|
||||
+ } else {
|
||||
+ event.respondWith(Promise.reject(Error("Invalid Request")));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
index 16ed737f63e8eee26a306c70acb0589e424db35d..ad2853b33dc7474293df1423dd8af459571736b9 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
@@ -8,6 +8,18 @@ function loadScript(url, { doc = document }={}) {
|
||||
})
|
||||
}
|
||||
|
||||
+function preloadImage(url, { doc = document }={}) {
|
||||
+ return new Promise((resolve, reject) => {
|
||||
+ const preload = doc.createElement('link');
|
||||
+ preload.rel = 'preload';
|
||||
+ preload.as = 'image';
|
||||
+ preload.onload = () => resolve();
|
||||
+ preload.onerror = () => resolve();
|
||||
+ preload.href = url;
|
||||
+ doc.body.appendChild(preload);
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
/**
|
||||
*
|
||||
* @param {Document} document
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
index 134b0a7abd817599921d4fb430e8247a2cb40f82..a9577f01727678cd7a76bcc65e132fd6fcb230ac 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
@@ -4,6 +4,7 @@ PASS Defer range header passthrough tests to service worker
|
||||
PASS Ranged response not allowed following no-cors ranged request
|
||||
PASS Non-opaque ranged response executed
|
||||
FAIL Accept-Encoding should not appear in a service worker assert_equals: Accept-Encoding should not be set for media expected (object) null but got (string) "identity;q=1, *;q=0"
|
||||
+PASS Opaque range preload successes and failures should be indistinguishable
|
||||
PASS Range headers correctly preserved
|
||||
PASS Range headers correctly removed
|
||||
PASS Headers correctly filtered
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
index 76f80e9416c615417ad2a9fbaa565641ff5b8a12..42e4ac6d75afdcbb2ad1e9d3e4069d9cbfd10dbd 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
@@ -149,3 +149,78 @@ promise_test(async t => {
|
||||
|
||||
assert_equals((await audioBroadcast).acceptEncoding, null, "Accept-Encoding should not be set for media");
|
||||
}, `Accept-Encoding should not appear in a service worker`);
|
||||
+
|
||||
+promise_test(async t => {
|
||||
+ const scope = BASE_SCOPE + Math.random();
|
||||
+ await setupRegistration(t, scope);
|
||||
+ const iframe = await with_iframe(scope);
|
||||
+ const w = iframe.contentWindow;
|
||||
+ const length = 100;
|
||||
+ const count = 3;
|
||||
+ const counts = {};
|
||||
+
|
||||
+ // test a single range request size
|
||||
+ async function testSizedRange(size, partialResponseCode) {
|
||||
+ const rangeId = Math.random() + '';
|
||||
+ const rangeBroadcast = awaitMessage(w.navigator.serviceWorker, rangeId);
|
||||
+
|
||||
+ // Create a bogus audo element to trick the browser into sending
|
||||
+ // cross-origin range requests that can be manipulated by the service worker.
|
||||
+ const sound_url = new URL('partial-text.py', w.location);
|
||||
+ sound_url.hostname = REMOTE_HOST;
|
||||
+ sound_url.searchParams.set('action', 'record-media-range-request');
|
||||
+ sound_url.searchParams.set('length', length);
|
||||
+ sound_url.searchParams.set('size', size);
|
||||
+ sound_url.searchParams.set('partial', partialResponseCode);
|
||||
+ sound_url.searchParams.set('id', rangeId);
|
||||
+ appendAudio(w.document, sound_url);
|
||||
+
|
||||
+ // wait for the range requests to happen
|
||||
+ await rangeBroadcast;
|
||||
+
|
||||
+ // Create multiple preload requests and count the number of resource timing
|
||||
+ // entries that get created to make sure 206 and 416 range responses are treated
|
||||
+ // the same.
|
||||
+ const url = new URL('partial-text.py', w.location);
|
||||
+ url.searchParams.set('action', 'use-media-range-request');
|
||||
+ url.searchParams.set('size', size);
|
||||
+ counts['size' + size] = 0;
|
||||
+ for (let i = 0; i < count; i++) {
|
||||
+ await preloadImage(url, { doc: w.document });
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Test range requests from 1 smaller than the correct size to 1 larger than
|
||||
+ // the correct size to exercise the various permutations using the default 206
|
||||
+ // response code for successful range requests.
|
||||
+ for (let size = length - 1; size <= length + 1; size++) {
|
||||
+ await testSizedRange(size, '206');
|
||||
+ }
|
||||
+
|
||||
+ // Test a successful range request using a 200 response.
|
||||
+ await testSizedRange(length - 2, '200');
|
||||
+
|
||||
+ // Check the resource timing entries and count the reported number of fetches of each type
|
||||
+ const resources = w.performance.getEntriesByType("resource");
|
||||
+ for (const entry of resources) {
|
||||
+ const url = new URL(entry.name);
|
||||
+ if (url.searchParams.has('action') &&
|
||||
+ url.searchParams.get('action') == 'use-media-range-request' &&
|
||||
+ url.searchParams.has('size')) {
|
||||
+ counts['size' + url.searchParams.get('size')]++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Make sure there are a non-zero number of preload requests and they are all the same
|
||||
+ let counts_valid = true;
|
||||
+ const first = 'size' + (length - 2);
|
||||
+ for (let size = length - 2; size <= length + 1; size++) {
|
||||
+ let key = 'size' + size;
|
||||
+ if (!(key in counts) || counts[key] <= 0 || counts[key] != counts[first]) {
|
||||
+ counts_valid = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ assert_true(counts_valid, `Opaque range request preloads were different for error and success`);
|
||||
+}, `Opaque range preload successes and failures should be indistinguishable`);
|
||||
72
patches/chromium/cherry-pick-e3805f29fed7.patch
Normal file
72
patches/chromium/cherry-pick-e3805f29fed7.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Ellis <kevers@google.com>
|
||||
Date: Fri, 11 Feb 2022 01:36:04 +0000
|
||||
Subject: Code health cleanup: replacing animations.
|
||||
|
||||
Animation::Update performed a synchronous processing of the finish
|
||||
microtask to ensure that finished events where dispatched ahead of
|
||||
replace events. This step does not align with the spec. Instead we
|
||||
should be queuing the replace event. Microtasks will be processed in
|
||||
the correct order.
|
||||
|
||||
Spec link: https://www.w3.org/TR/web-animations-1/#timelines
|
||||
|
||||
Change-Id: Ibe7753e792fb6cf905bbe6815a080a8cc51c2803
|
||||
|
||||
(cherry picked from commit d4fb69ff0fe343fe8a171014785a88eabfe2b1c2)
|
||||
|
||||
Bug: 1290858
|
||||
Change-Id: Ibe7753e792fb6cf905bbe6815a080a8cc51c2803
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3414765
|
||||
Reviewed-by: Mustaq Ahmed <mustaq@chromium.org>
|
||||
Commit-Queue: Kevin Ellis <kevers@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#964223}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3453925
|
||||
Reviewed-by: Adrian Taylor <adetaylor@google.com>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1134}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
|
||||
index 545dcd7f0faae91cee574fce60fdedb4f6903bb6..96ecc0bf8c7dbb01714f680b6f0930d1e801f4a8 100644
|
||||
--- a/third_party/blink/renderer/core/animation/animation.cc
|
||||
+++ b/third_party/blink/renderer/core/animation/animation.cc
|
||||
@@ -2232,10 +2232,6 @@ bool Animation::Update(TimingUpdateReason reason) {
|
||||
|
||||
if (reason == kTimingUpdateForAnimationFrame) {
|
||||
if (idle || CalculateAnimationPlayState() == kFinished) {
|
||||
- // TODO(crbug.com/1029348): Per spec, we should have a microtask
|
||||
- // checkpoint right after the update cycle. Once this is fixed we should
|
||||
- // no longer need to force a synchronous resolution here.
|
||||
- AsyncFinishMicrotask();
|
||||
finished_ = true;
|
||||
}
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/animation/document_animations.cc b/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
index 6e5b4f970387929b6b940b18e14e997d2baa339c..f8090e41f8b0aa2e138738f5a3ba7c434d85535b 100644
|
||||
--- a/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
+++ b/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "third_party/blink/renderer/core/page/page.h"
|
||||
#include "third_party/blink/renderer/core/page/page_animator.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/microtask.h"
|
||||
+#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -286,10 +287,13 @@ void DocumentAnimations::RemoveReplacedAnimations(
|
||||
|
||||
// The list of animations for removal is constructed in reverse composite
|
||||
// ordering for efficiency. Flip the ordering to ensure that events are
|
||||
- // dispatched in composite order.
|
||||
+ // dispatched in composite order. Queue as a microtask so that the finished
|
||||
+ // event is dispatched ahead of the remove event.
|
||||
for (auto it = animations_to_remove.rbegin();
|
||||
it != animations_to_remove.rend(); it++) {
|
||||
- (*it)->RemoveReplacedAnimation();
|
||||
+ Animation* animation = *it;
|
||||
+ Microtask::EnqueueMicrotask(WTF::Bind(&Animation::RemoveReplacedAnimation,
|
||||
+ WrapWeakPersistent(animation)));
|
||||
}
|
||||
}
|
||||
|
||||
55
patches/chromium/cherry-pick-ebc188ad769e.patch
Normal file
55
patches/chromium/cherry-pick-ebc188ad769e.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Sat, 5 Feb 2022 13:41:47 +0000
|
||||
Subject: Fix potential handle reuse in Mojo
|
||||
|
||||
(cherry picked from commit 76eca90d0e9c09bfbb8c3e8999f36e6da6842a39)
|
||||
|
||||
(cherry picked from commit e1432faf5e101b3a516037a26818c03c759d2fdd)
|
||||
|
||||
Fixed: 1270333
|
||||
Change-Id: Ife188d519092e4e634355fd53d97c85009771b76
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3414063
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/main@{#962946}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3421488
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4844@{#87}
|
||||
Cr-Original-Branched-From: 007241ce2e6c8e5a7b306cc36c730cd07cd38825-refs/heads/main@{#961656}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3427544
|
||||
Reviewed-by: Jana Grill <janagrill@google.com>
|
||||
Owners-Override: Jana Grill <janagrill@google.com>
|
||||
Commit-Queue: Zakhar Voit <voit@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1455}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/mojo/core/handle_table.cc b/mojo/core/handle_table.cc
|
||||
index 9426281d73f050598bd5f88b38aac39c4b994ff3..a044f1c8e38f0affe269a87a10c70b49fe6d353c 100644
|
||||
--- a/mojo/core/handle_table.cc
|
||||
+++ b/mojo/core/handle_table.cc
|
||||
@@ -65,13 +65,19 @@ bool HandleTable::AddDispatchersFromTransit(
|
||||
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
|
||||
MojoHandle* handles) {
|
||||
// Oops, we're out of handles.
|
||||
- if (next_available_handle_ == MOJO_HANDLE_INVALID)
|
||||
+ if (next_available_handle_ == MOJO_HANDLE_INVALID) {
|
||||
return false;
|
||||
+ }
|
||||
+
|
||||
+ // MOJO_HANDLE_INVALID is zero.
|
||||
+ DCHECK_GE(next_available_handle_, 1u);
|
||||
|
||||
- DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
|
||||
// If this insertion would cause handle overflow, we're out of handles.
|
||||
- if (next_available_handle_ + dispatchers.size() < next_available_handle_)
|
||||
+ const uint32_t num_handles_available =
|
||||
+ std::numeric_limits<uint32_t>::max() - next_available_handle_ + 1;
|
||||
+ if (num_handles_available < dispatchers.size()) {
|
||||
return false;
|
||||
+ }
|
||||
|
||||
for (size_t i = 0; i < dispatchers.size(); ++i) {
|
||||
MojoHandle handle = MOJO_HANDLE_INVALID;
|
||||
245
patches/chromium/cherry-pick-f0a63e1f361f.patch
Normal file
245
patches/chromium/cherry-pick-f0a63e1f361f.patch
Normal file
@@ -0,0 +1,245 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Rice <ricea@chromium.org>
|
||||
Date: Sat, 6 Nov 2021 18:52:26 +0000
|
||||
Subject: Return undefined from UnderlyingSinkBase "type" getter
|
||||
|
||||
The "type" attribute of an object passed to the WritableStream
|
||||
constructor is supposed to return undefined. Add a getter to
|
||||
UnderlyingSinkBase to ensure it always does.
|
||||
|
||||
Add tests to verify that "type" is not inherited from
|
||||
Object.prototype.type.
|
||||
|
||||
Move some methods out-of-line into a new underlying_sink_base.cc file.
|
||||
|
||||
Make WritableStreamDefaultController::From() more robust.
|
||||
|
||||
BUG=1262791
|
||||
|
||||
(cherry picked from commit 26564c88bc9e034cc512afd857cf303193647b9a)
|
||||
|
||||
Change-Id: I97f43233eef0e473fb1a22a3ea8afafe92e16266
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3252171
|
||||
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
|
||||
Commit-Queue: Adam Rice <ricea@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936834}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3266824
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#806}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/streams/build.gni b/third_party/blink/renderer/core/streams/build.gni
|
||||
index 57a106353bd6720bc7da88f96dce66e4332aea2a..744d47f1a1e9352cc4df56ce89635b3d6f8b5425 100644
|
||||
--- a/third_party/blink/renderer/core/streams/build.gni
|
||||
+++ b/third_party/blink/renderer/core/streams/build.gni
|
||||
@@ -43,6 +43,7 @@ blink_core_sources_streams = [
|
||||
"transform_stream_default_controller.cc",
|
||||
"transform_stream_default_controller.h",
|
||||
"transform_stream_transformer.h",
|
||||
+ "underlying_sink_base.cc",
|
||||
"underlying_sink_base.h",
|
||||
"underlying_source_base.cc",
|
||||
"underlying_source_base.h",
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.cc b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a10d4f1865fc4e11c90f463b64ff666cce0fba69
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
|
||||
@@ -0,0 +1,29 @@
|
||||
+// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
|
||||
+
|
||||
+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
+#include "v8/include/v8.h"
|
||||
+
|
||||
+namespace blink {
|
||||
+
|
||||
+ScriptPromise UnderlyingSinkBase::start(ScriptState* script_state,
|
||||
+ ScriptValue controller,
|
||||
+ ExceptionState& exception_state) {
|
||||
+ controller_ = WritableStreamDefaultController::From(script_state, controller);
|
||||
+ return start(script_state, controller_, exception_state);
|
||||
+}
|
||||
+
|
||||
+ScriptValue UnderlyingSinkBase::type(ScriptState* script_state) const {
|
||||
+ auto* isolate = script_state->GetIsolate();
|
||||
+ return ScriptValue(isolate, v8::Undefined(isolate));
|
||||
+}
|
||||
+
|
||||
+void UnderlyingSinkBase::Trace(Visitor* visitor) const {
|
||||
+ visitor->Trace(controller_);
|
||||
+ ScriptWrappable::Trace(visitor);
|
||||
+}
|
||||
+
|
||||
+} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.h b/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
index 3b07d87f064a26e01c4ee827d78fca005049c90a..07ba729fc3a78cf2102e2d64e527048af8be9c71 100644
|
||||
--- a/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
@@ -6,16 +6,20 @@
|
||||
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_UNDERLYING_SINK_BASE_H_
|
||||
|
||||
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
|
||||
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
|
||||
#include "third_party/blink/renderer/core/core_export.h"
|
||||
-#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
|
||||
#include "third_party/blink/renderer/platform/heap/visitor.h"
|
||||
|
||||
+// Various files depend on us exporting this header.
|
||||
+// TODO(ricea): Clean up the dependencies and remove this include.
|
||||
+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
+
|
||||
namespace blink {
|
||||
|
||||
class ExceptionState;
|
||||
-class ScriptValue;
|
||||
class ScriptState;
|
||||
+class WritableStreamDefaultController;
|
||||
|
||||
class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
@@ -38,12 +42,8 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
ScriptValue reason,
|
||||
ExceptionState&) = 0;
|
||||
|
||||
- ScriptPromise start(ScriptState* script_state,
|
||||
- ScriptValue controller,
|
||||
- ExceptionState& exception_state) {
|
||||
- controller_ = WritableStreamDefaultController::From(controller);
|
||||
- return start(script_state, controller_, exception_state);
|
||||
- }
|
||||
+ ScriptPromise start(ScriptState*, ScriptValue controller, ExceptionState&);
|
||||
+
|
||||
ScriptPromise write(ScriptState* script_state,
|
||||
ScriptValue chunk,
|
||||
ScriptValue controller,
|
||||
@@ -52,10 +52,11 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
return write(script_state, chunk, controller_, exception_state);
|
||||
}
|
||||
|
||||
- void Trace(Visitor* visitor) const override {
|
||||
- visitor->Trace(controller_);
|
||||
- ScriptWrappable::Trace(visitor);
|
||||
- }
|
||||
+ // Returns a JavaScript "undefined" value. This is required by the
|
||||
+ // WritableStream Create() method.
|
||||
+ ScriptValue type(ScriptState*) const;
|
||||
+
|
||||
+ void Trace(Visitor*) const override;
|
||||
|
||||
protected:
|
||||
WritableStreamDefaultController* Controller() const { return controller_; }
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.idl b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
index 8351141cbc07ed32566a0006f998aab61e8fd6b5..470eb527b11e3dce355d724eaa63ec981b7788e4 100644
|
||||
--- a/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
@@ -14,4 +14,7 @@ interface UnderlyingSinkBase {
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> write(any chunk, any controller);
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> close();
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> abort(any reason);
|
||||
+
|
||||
+ // This only exists to prevent Object.prototype.type being accessed.
|
||||
+ [CallWith=ScriptState] readonly attribute any type;
|
||||
};
|
||||
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
index 0b22eedcddc87b0ac695389a76ed5e353dd5f92c..bc959b6c33dbba6a367b4d247d56b67698299635 100644
|
||||
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
@@ -20,10 +20,14 @@
|
||||
namespace blink {
|
||||
|
||||
WritableStreamDefaultController* WritableStreamDefaultController::From(
|
||||
+ ScriptState* script_state,
|
||||
ScriptValue controller) {
|
||||
- DCHECK(controller.IsObject());
|
||||
- return V8WritableStreamDefaultController::ToImpl(
|
||||
- controller.V8Value().As<v8::Object>());
|
||||
+ CHECK(controller.IsObject());
|
||||
+ auto* controller_impl =
|
||||
+ V8WritableStreamDefaultController::ToImplWithTypeCheck(
|
||||
+ script_state->GetIsolate(), controller.V8Value().As<v8::Object>());
|
||||
+ CHECK(controller_impl);
|
||||
+ return controller_impl;
|
||||
}
|
||||
|
||||
// Only used internally. Not reachable from JavaScript.
|
||||
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
index 3351dcd6941360fc9fecaa8c03080da813a5b6a2..8be676421763caa911b8d003c869856675e28713 100644
|
||||
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
@@ -27,7 +27,7 @@ class CORE_EXPORT WritableStreamDefaultController final
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
|
||||
public:
|
||||
- static WritableStreamDefaultController* From(ScriptValue);
|
||||
+ static WritableStreamDefaultController* From(ScriptState*, ScriptValue);
|
||||
|
||||
// The JavaScript-exposed constructor throws automatically as no constructor
|
||||
// is specified in the IDL. This constructor is used internally during
|
||||
diff --git a/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fbbc26b08ea4e310ed99b7a02e1a7952e8f60921
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
|
||||
@@ -0,0 +1,57 @@
|
||||
+<!DOCTYPE html>
|
||||
+<meta charset="utf-8">
|
||||
+<script src="/resources/testharness.js"></script>
|
||||
+<script src="/resources/testharnessreport.js"></script>
|
||||
+<script>
|
||||
+'use strict';
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ throw Error();
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ // The WritableStream is created lazily, so access it to trigger creation.
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a throwing getter on Object.prototype.type should not interfere with ' +
|
||||
+ 'native writable stream creation');
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ this.start(0x414141);
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a getter that calls start() with a number on Object.prototype.type ' +
|
||||
+ 'should not interfere with native writable stream creation');
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ this.start({});
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a getter that calls start() with an object on Object.prototype.type ' +
|
||||
+ 'should not interfere with native writable stream creation');
|
||||
+
|
||||
+</script>
|
||||
195
patches/chromium/cherry-pick-f781748dcb3c.patch
Normal file
195
patches/chromium/cherry-pick-f781748dcb3c.patch
Normal file
@@ -0,0 +1,195 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ravjit <ravjit@chromium.org>
|
||||
Date: Thu, 16 Sep 2021 12:29:55 +0000
|
||||
Subject: Show the origin of the last redirecting server in external protocol
|
||||
handler dialogs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
External protocol handlers always show the initiating url's origin. This can be misleading if there are server side redirects.
|
||||
Now we will show the origin of the last redirecting server (falling back to the request_initiator if there were no redirects / if the request goes straight to an external protocol).
|
||||
|
||||
Bug: 1197889
|
||||
Change-Id: I3cf7ccf3a8bd79d161364680a1871d1c88bec813
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3113931
|
||||
Commit-Queue: Ravjit Singh Uppal <ravjit@chromium.org>
|
||||
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Reviewed-by: Collin Baker <collinbaker@chromium.org>
|
||||
Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
|
||||
Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#922096}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
index 7e953fe89ff8dadf4da9578c0fdc6c3aada11aca..5c7e331ea4fbbcf36ac6463b37884cc9c6ca7e41 100644
|
||||
--- a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
+++ b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
@@ -14,11 +14,15 @@
|
||||
#include "chrome/browser/ui/test/test_browser_dialog.h"
|
||||
#include "chrome/browser/ui/views/external_protocol_dialog.h"
|
||||
#include "chrome/test/base/in_process_browser_test.h"
|
||||
+#include "chrome/test/base/ui_test_utils.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/test/browser_test.h"
|
||||
+#include "net/dns/mock_host_resolver.h"
|
||||
+#include "net/test/embedded_test_server/http_request.h"
|
||||
+#include "net/test/embedded_test_server/http_response.h"
|
||||
#include "ui/views/controls/button/checkbox.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@@ -41,6 +45,33 @@ class ExternalProtocolDialogTestApi {
|
||||
|
||||
} // namespace test
|
||||
|
||||
+namespace {
|
||||
+constexpr char kInitiatingOrigin[] = "a.test";
|
||||
+constexpr char kRedirectingOrigin[] = "b.test";
|
||||
+
|
||||
+class FakeDefaultProtocolClientWorker
|
||||
+ : public shell_integration::DefaultProtocolClientWorker {
|
||||
+ public:
|
||||
+ explicit FakeDefaultProtocolClientWorker(const std::string& protocol)
|
||||
+ : DefaultProtocolClientWorker(protocol) {}
|
||||
+ FakeDefaultProtocolClientWorker(const FakeDefaultProtocolClientWorker&) =
|
||||
+ delete;
|
||||
+ FakeDefaultProtocolClientWorker& operator=(
|
||||
+ const FakeDefaultProtocolClientWorker&) = delete;
|
||||
+
|
||||
+ private:
|
||||
+ ~FakeDefaultProtocolClientWorker() override = default;
|
||||
+ shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
|
||||
+ return shell_integration::DefaultWebClientState::NOT_DEFAULT;
|
||||
+ }
|
||||
+
|
||||
+ void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override {
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE, std::move(on_finished_callback));
|
||||
+ }
|
||||
+};
|
||||
+} // namespace
|
||||
+
|
||||
class ExternalProtocolDialogBrowserTest
|
||||
: public DialogBrowserTest,
|
||||
public ExternalProtocolHandler::Delegate {
|
||||
@@ -71,11 +102,11 @@ class ExternalProtocolDialogBrowserTest
|
||||
// ExternalProtocolHander::Delegate:
|
||||
scoped_refptr<shell_integration::DefaultProtocolClientWorker>
|
||||
CreateShellWorker(const std::string& protocol) override {
|
||||
- return nullptr;
|
||||
+ return base::MakeRefCounted<FakeDefaultProtocolClientWorker>(protocol);
|
||||
}
|
||||
ExternalProtocolHandler::BlockState GetBlockState(const std::string& scheme,
|
||||
Profile* profile) override {
|
||||
- return ExternalProtocolHandler::DONT_BLOCK;
|
||||
+ return ExternalProtocolHandler::UNKNOWN;
|
||||
}
|
||||
void BlockRequest() override {}
|
||||
void RunExternalProtocolDialog(
|
||||
@@ -83,7 +114,10 @@ class ExternalProtocolDialogBrowserTest
|
||||
content::WebContents* web_contents,
|
||||
ui::PageTransition page_transition,
|
||||
bool has_user_gesture,
|
||||
- const absl::optional<url::Origin>& initiating_origin) override {}
|
||||
+ const absl::optional<url::Origin>& initiating_origin) override {
|
||||
+ url_did_launch_ = true;
|
||||
+ launch_url_ = initiating_origin->host();
|
||||
+ }
|
||||
void LaunchUrlWithoutSecurityCheck(
|
||||
const GURL& url,
|
||||
content::WebContents* web_contents) override {
|
||||
@@ -98,6 +132,12 @@ class ExternalProtocolDialogBrowserTest
|
||||
blocked_state_ = state;
|
||||
}
|
||||
|
||||
+ void SetUpOnMainThread() override {
|
||||
+ DialogBrowserTest::SetUpOnMainThread();
|
||||
+ host_resolver()->AddRule(kInitiatingOrigin, "127.0.0.1");
|
||||
+ host_resolver()->AddRule(kRedirectingOrigin, "127.0.0.1");
|
||||
+ }
|
||||
+
|
||||
base::HistogramTester histogram_tester_;
|
||||
|
||||
protected:
|
||||
@@ -106,6 +146,7 @@ class ExternalProtocolDialogBrowserTest
|
||||
url::Origin blocked_origin_;
|
||||
BlockState blocked_state_ = BlockState::UNKNOWN;
|
||||
bool url_did_launch_ = false;
|
||||
+ std::string launch_url_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ExternalProtocolDialogBrowserTest);
|
||||
@@ -231,3 +272,21 @@ IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestFocus) {
|
||||
const views::View* focused_view = focus_manager->GetFocusedView();
|
||||
EXPECT_TRUE(focused_view);
|
||||
}
|
||||
+
|
||||
+IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, OriginNameTest) {
|
||||
+ ASSERT_TRUE(embedded_test_server()->Start());
|
||||
+ content::WebContents* web_contents =
|
||||
+ browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(
|
||||
+ browser(), embedded_test_server()->GetURL("a.test", "/empty.html")));
|
||||
+ EXPECT_TRUE(content::ExecJs(
|
||||
+ web_contents,
|
||||
+ content::JsReplace("location.href = $1",
|
||||
+ embedded_test_server()->GetURL(
|
||||
+ "b.test", "/server-redirect?ms-calc:"))));
|
||||
+ content::WaitForLoadStop(web_contents);
|
||||
+ EXPECT_TRUE(url_did_launch_);
|
||||
+ // The url should be the url of the last redirecting server and not of the
|
||||
+ // request initiator
|
||||
+ EXPECT_EQ(launch_url_, "b.test");
|
||||
+}
|
||||
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
|
||||
index 4d0c1a27449d5f88a4a88c915a3d741df42d4613..8174e746f76337716cdcbf6eba4fd54cacb12a0a 100644
|
||||
--- a/content/browser/loader/navigation_url_loader_impl.cc
|
||||
+++ b/content/browser/loader/navigation_url_loader_impl.cc
|
||||
@@ -621,6 +621,13 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
|
||||
if (known_schemes_.find(resource_request_->url.scheme()) ==
|
||||
known_schemes_.end()) {
|
||||
mojo::PendingRemote<network::mojom::URLLoaderFactory> loader_factory;
|
||||
+ absl::optional<url::Origin> initiating_origin;
|
||||
+ if (url_chain_.size() > 1) {
|
||||
+ initiating_origin =
|
||||
+ url::Origin::Create(url_chain_[url_chain_.size() - 2]);
|
||||
+ } else {
|
||||
+ initiating_origin = resource_request_->request_initiator;
|
||||
+ }
|
||||
bool handled = GetContentClient()->browser()->HandleExternalProtocol(
|
||||
resource_request_->url, web_contents_getter_,
|
||||
ChildProcessHost::kInvalidUniqueID, frame_tree_node_id_,
|
||||
@@ -628,8 +635,8 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
|
||||
resource_request_->resource_type ==
|
||||
static_cast<int>(blink::mojom::ResourceType::kMainFrame),
|
||||
static_cast<ui::PageTransition>(resource_request_->transition_type),
|
||||
- resource_request_->has_user_gesture,
|
||||
- resource_request_->request_initiator, &loader_factory);
|
||||
+ resource_request_->has_user_gesture, initiating_origin,
|
||||
+ &loader_factory);
|
||||
|
||||
if (loader_factory) {
|
||||
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index e07f51020fc2139a9757b8d52bd5f5a002e1c561..db802c5a3354e10567f3ab559168965add3cd59a 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -1754,10 +1754,12 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
// Otherwise child_id will be the process id and |navigation_ui_data| will be
|
||||
// nullptr.
|
||||
//
|
||||
- // |initiating_origin| is the origin that initiated the navigation to the
|
||||
- // external protocol, and may be null, e.g. in the case of browser-initiated
|
||||
- // navigations. The initiating origin is intended to help users make security
|
||||
- // decisions about whether to allow an external application to launch.
|
||||
+ // |initiating_origin| is the origin of the last redirecting server (falling
|
||||
+ // back to the request initiator if there were no redirects / if the request
|
||||
+ // goes straight to an external protocol, or null, e.g. in the case of
|
||||
+ // browser-initiated navigations. The initiating origin is intended to help
|
||||
+ // users make security decisions about whether to allow an external
|
||||
+ // application to launch.
|
||||
virtual bool HandleExternalProtocol(
|
||||
const GURL& url,
|
||||
base::RepeatingCallback<WebContents*()> web_contents_getter,
|
||||
138
patches/chromium/cleanup_pausablecriptexecutor_usage.patch
Normal file
138
patches/chromium/cleanup_pausablecriptexecutor_usage.patch
Normal file
@@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Tapuska <dtapuska@chromium.org>
|
||||
Date: Tue, 8 Feb 2022 15:58:40 +0000
|
||||
Subject: Cleanup PausablecriptExecutor usage.
|
||||
|
||||
Improve performance of API so we don't have to go from
|
||||
WTF::String->WebString->WTF::String for execution.
|
||||
|
||||
Ensure the Executor is traced via the PausableScriptExecutor.
|
||||
|
||||
BUG=1289384
|
||||
|
||||
(cherry picked from commit c8231f9a89460fd8336e6c0d8e10347f52f540ec)
|
||||
|
||||
Change-Id: If9badab91222c49c08a983c60132ce71b183e951
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3407654
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#963010}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3443262
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1109}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
index 08af6a3d5d457afa9f5ac4815f64cce1e520c9a4..8daa90b37b50f916a6ad82cefb81891acb9c4bdc 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
@@ -210,15 +210,16 @@ v8::MaybeLocal<v8::Value> CallMethodOnFrame(LocalFrame* local_frame,
|
||||
|
||||
// A wrapper class used as the callback for JavaScript executed
|
||||
// in an isolated world.
|
||||
-class JavaScriptIsolatedWorldRequest
|
||||
- : public GarbageCollected<JavaScriptIsolatedWorldRequest>,
|
||||
- public WebScriptExecutionCallback {
|
||||
+class JavaScriptIsolatedWorldRequest : public PausableScriptExecutor::Executor,
|
||||
+ public WebScriptExecutionCallback {
|
||||
using JavaScriptExecuteRequestInIsolatedWorldCallback =
|
||||
mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback;
|
||||
|
||||
public:
|
||||
JavaScriptIsolatedWorldRequest(
|
||||
LocalFrame* local_frame,
|
||||
+ int32_t world_id,
|
||||
+ const String& script,
|
||||
bool wants_result,
|
||||
mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback
|
||||
callback);
|
||||
@@ -228,27 +229,53 @@ class JavaScriptIsolatedWorldRequest
|
||||
const JavaScriptIsolatedWorldRequest&) = delete;
|
||||
~JavaScriptIsolatedWorldRequest() override;
|
||||
|
||||
- // WebScriptExecutionCallback:
|
||||
- void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
|
||||
+ // PausableScriptExecutor::Executor overrides.
|
||||
+ Vector<v8::Local<v8::Value>> Execute(LocalDOMWindow*) override;
|
||||
+
|
||||
+ void Trace(Visitor* visitor) const override;
|
||||
|
||||
- void Trace(Visitor* visitor) const { visitor->Trace(local_frame_); }
|
||||
+ // WebScriptExecutionCallback overrides.
|
||||
+ void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
|
||||
|
||||
private:
|
||||
Member<LocalFrame> local_frame_;
|
||||
+ int32_t world_id_;
|
||||
+ String script_;
|
||||
bool wants_result_;
|
||||
JavaScriptExecuteRequestInIsolatedWorldCallback callback_;
|
||||
};
|
||||
|
||||
JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest(
|
||||
LocalFrame* local_frame,
|
||||
+ int32_t world_id,
|
||||
+ const String& script,
|
||||
bool wants_result,
|
||||
JavaScriptExecuteRequestInIsolatedWorldCallback callback)
|
||||
: local_frame_(local_frame),
|
||||
+ world_id_(world_id),
|
||||
+ script_(script),
|
||||
wants_result_(wants_result),
|
||||
- callback_(std::move(callback)) {}
|
||||
+ callback_(std::move(callback)) {
|
||||
+ DCHECK_GT(world_id, DOMWrapperWorld::kMainWorldId);
|
||||
+}
|
||||
|
||||
JavaScriptIsolatedWorldRequest::~JavaScriptIsolatedWorldRequest() = default;
|
||||
|
||||
+void JavaScriptIsolatedWorldRequest::Trace(Visitor* visitor) const {
|
||||
+ PausableScriptExecutor::Executor::Trace(visitor);
|
||||
+ visitor->Trace(local_frame_);
|
||||
+}
|
||||
+
|
||||
+Vector<v8::Local<v8::Value>> JavaScriptIsolatedWorldRequest::Execute(
|
||||
+ LocalDOMWindow* window) {
|
||||
+ // Note: An error event in an isolated world will never be dispatched to
|
||||
+ // a foreign world.
|
||||
+ ClassicScript* classic_script = ClassicScript::CreateUnspecifiedScript(
|
||||
+ script_, SanitizeScriptErrors::kDoNotSanitize);
|
||||
+ return {classic_script->RunScriptInIsolatedWorldAndReturnValue(window,
|
||||
+ world_id_)};
|
||||
+}
|
||||
+
|
||||
void JavaScriptIsolatedWorldRequest::Completed(
|
||||
const WebVector<v8::Local<v8::Value>>& result) {
|
||||
base::Value value;
|
||||
@@ -268,7 +295,6 @@ void JavaScriptIsolatedWorldRequest::Completed(
|
||||
if (new_value)
|
||||
value = base::Value::FromUniquePtrValue(std::move(new_value));
|
||||
}
|
||||
-
|
||||
std::move(callback_).Run(std::move(value));
|
||||
}
|
||||
|
||||
@@ -849,13 +875,16 @@ void LocalFrameMojoHandler::JavaScriptExecuteRequestInIsolatedWorld(
|
||||
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
|
||||
scoped_refptr<DOMWrapperWorld> isolated_world =
|
||||
DOMWrapperWorld::EnsureIsolatedWorld(ToIsolate(frame_), world_id);
|
||||
- ScriptSourceCode source_code = ScriptSourceCode(javascript);
|
||||
- HeapVector<ScriptSourceCode> sources;
|
||||
- sources.Append(&source_code, 1);
|
||||
- auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
|
||||
- DomWindow(), std::move(isolated_world), sources, false /* user_gesture */,
|
||||
+
|
||||
+ // This member will be traced as the |executor| on the PausableScriptExector.
|
||||
+ auto* execution_request =
|
||||
MakeGarbageCollected<JavaScriptIsolatedWorldRequest>(
|
||||
- frame_, wants_result, std::move(callback)));
|
||||
+ frame_, world_id, javascript, wants_result, std::move(callback));
|
||||
+
|
||||
+ auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
|
||||
+ DomWindow(), ToScriptState(frame_, *isolated_world),
|
||||
+ /*callback=*/execution_request,
|
||||
+ /*executor=*/execution_request);
|
||||
executor->Run();
|
||||
}
|
||||
|
||||
@@ -59,45 +59,42 @@ index 9aec54a3263d24491d24013a80b719dfc834ecd4..001a6cb2a5eb701351fa924109b43fab
|
||||
// true if register successfully, or false if 1) the specificied |accelerator|
|
||||
// has been registered by another caller or other native applications, or
|
||||
diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
index 5938f75742b793868638e693a9a8c8dc686dfc46..1263d679a5174beb960265989c370dd4a58ae7b4 100644
|
||||
index 5938f75742b793868638e693a9a8c8dc686dfc46..afeca1ede732543c4769fe47e5b41a6444a3bf6f 100644
|
||||
--- a/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
+++ b/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
@@ -231,18 +231,24 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
|
||||
media::AudioManager::GetGlobalAppName());
|
||||
@@ -232,18 +232,26 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
|
||||
#endif
|
||||
|
||||
- if (system_media_controls_) {
|
||||
- system_media_controls_->AddObserver(this);
|
||||
- system_media_controls_notifier_ =
|
||||
- std::make_unique<SystemMediaControlsNotifier>(
|
||||
- system_media_controls_.get());
|
||||
if (system_media_controls_) {
|
||||
+ // This is required for proper functioning of MediaMetadata.
|
||||
system_media_controls_->AddObserver(this);
|
||||
system_media_controls_notifier_ =
|
||||
std::make_unique<SystemMediaControlsNotifier>(
|
||||
system_media_controls_.get());
|
||||
- } else {
|
||||
- // If we can't access system media controls, then directly listen for media
|
||||
- // key keypresses instead.
|
||||
+ // This is required for proper functioning of MediaMetadata.
|
||||
+ system_media_controls_->AddObserver(this);
|
||||
+ system_media_controls_notifier_ =
|
||||
+ std::make_unique<SystemMediaControlsNotifier>(
|
||||
+ system_media_controls_.get());
|
||||
+
|
||||
- media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
- this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
- DCHECK(media_keys_listener_);
|
||||
}
|
||||
|
||||
+ // Directly listen for media key keypresses when using GlobalShortcuts.
|
||||
+#if defined(OS_MACOS)
|
||||
+ auto scope = media_key_handling_enabled_ ?
|
||||
+ ui::MediaKeysListener::Scope::kGlobal :
|
||||
+ ui::MediaKeysListener::Scope::kGlobalRequiresAccessibility;
|
||||
media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
- this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
- DCHECK(media_keys_listener_);
|
||||
- }
|
||||
+ media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
+ this, scope);
|
||||
+#else
|
||||
+ media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
+ this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
+#endif
|
||||
+ DCHECK(media_keys_listener_);
|
||||
|
||||
+
|
||||
EnsureAuxiliaryServices();
|
||||
}
|
||||
|
||||
diff --git a/ui/base/accelerators/media_keys_listener.h b/ui/base/accelerators/media_keys_listener.h
|
||||
index c2b03328c0e508995bdc135031500783f500ceba..1b6b14dc2999c99445cef6ffc04d49a7c1728a54 100644
|
||||
--- a/ui/base/accelerators/media_keys_listener.h
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Date: Tue, 16 Nov 2021 22:16:15 +0000
|
||||
Subject: M96: [FileAPI] Move origin checks in BlobURLStore sooner.
|
||||
|
||||
Rather than waiting to verify if a valid origin was passed in until
|
||||
register/revoke time, check if the origin is valid at the time the
|
||||
mojo interface is requested. This avoids the need to pass the
|
||||
delegate on to BlobURLStoreImpl, further decoupling this from
|
||||
BlobRegistryImpl.
|
||||
|
||||
(cherry picked from commit 15cfa2bed3ce9dcdd0a06d3cd3b8330e3591acdc)
|
||||
|
||||
Bug: 1262183
|
||||
Change-Id: I4889685d03501158abfe4f87c647dc468d005f78
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3264353
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940015}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3285385
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1078}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
index ca2f5cbbaa845d281b44e60ff93e0ba536961d24..8be1504b801e6690d94d7e68fcd4f3b0e43e9862 100644
|
||||
--- a/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
+++ b/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
@@ -483,8 +483,8 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
|
||||
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
- "Received bad user message: Non committable URL passed to "
|
||||
- "BlobURLStore::Register",
|
||||
+ "Received bad user message: "
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
|
||||
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
- "Received bad user message: Non committable URL passed to "
|
||||
- "BlobURLStore::Register",
|
||||
+ "Received bad user message: "
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc
|
||||
index 317ce6c282abc81f472b7c911d9a2eabdb86a1d4..66360f2ab627f85935734320ab6ac402d5fe4bd5 100644
|
||||
--- a/content/browser/blob_storage/blob_url_unittest.cc
|
||||
+++ b/content/browser/blob_storage/blob_url_unittest.cc
|
||||
@@ -184,15 +184,14 @@ class BlobURLTest : public testing::Test {
|
||||
|
||||
void TestRequest(const std::string& method,
|
||||
const net::HttpRequestHeaders& extra_headers) {
|
||||
- GURL url("blob:blah");
|
||||
+ auto origin = url::Origin::Create(GURL("https://example.com"));
|
||||
+ auto url = GURL("blob:" + origin.Serialize() + "/id1");
|
||||
network::ResourceRequest request;
|
||||
request.url = url;
|
||||
request.method = method;
|
||||
request.headers = extra_headers;
|
||||
|
||||
- storage::MockBlobRegistryDelegate delegate;
|
||||
- storage::BlobURLStoreImpl url_store(blob_url_registry_.AsWeakPtr(),
|
||||
- &delegate);
|
||||
+ storage::BlobURLStoreImpl url_store(origin, blob_url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob_remote;
|
||||
storage::BlobImpl::Create(
|
||||
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
|
||||
index 5073d38cef7124b7ca1d0b38da2fcdc8683e45fb..eb5cb552c4e5d71cae2958c93d99645ce3d040b2 100644
|
||||
--- a/content/browser/security_exploit_browsertest.cc
|
||||
+++ b/content/browser/security_exploit_browsertest.cc
|
||||
@@ -782,7 +782,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestMojoBlobURLs,
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
"Received bad user message: "
|
||||
- "Non committable URL passed to BlobURLStore::Register",
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
|
||||
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
|
||||
index c01eb0635324a171a64c6c13b4ef7288b3f5de45..7c7686309f799f25ce30ec1dc18c75e608829ee2 100644
|
||||
--- a/storage/browser/blob/blob_registry_impl.cc
|
||||
+++ b/storage/browser/blob/blob_registry_impl.cc
|
||||
@@ -634,13 +634,14 @@ void BlobRegistryImpl::GetBlobFromUUID(
|
||||
void BlobRegistryImpl::URLStoreForOrigin(
|
||||
const url::Origin& origin,
|
||||
mojo::PendingAssociatedReceiver<blink::mojom::BlobURLStore> receiver) {
|
||||
- // TODO(mek): Pass origin on to BlobURLStoreImpl so it can use it to generate
|
||||
- // Blob URLs, and verify at this point that the renderer can create URLs for
|
||||
- // that origin.
|
||||
Delegate* delegate = receivers_.current_context().get();
|
||||
DCHECK(delegate);
|
||||
+ if (!origin.opaque() && !delegate->CanCommitURL(origin.GetURL())) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ "Non committable origin passed to BlobRegistryImpl::URLStoreForOrigin");
|
||||
+ }
|
||||
auto self_owned_associated_receiver = mojo::MakeSelfOwnedAssociatedReceiver(
|
||||
- std::make_unique<BlobURLStoreImpl>(url_registry_, delegate),
|
||||
+ std::make_unique<BlobURLStoreImpl>(origin, url_registry_),
|
||||
std::move(receiver));
|
||||
if (g_url_store_creation_hook)
|
||||
g_url_store_creation_hook->Run(self_owned_associated_receiver);
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc
|
||||
index b46ee60849c9b758e022d7e576de61b080fd59f5..d4edd988f5982788f5157d27fbfa31abcb1eede7 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl.cc
|
||||
+++ b/storage/browser/blob/blob_url_store_impl.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "storage/browser/blob/blob_url_store_impl.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
+#include "base/strings/strcat.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "storage/browser/blob/blob_impl.h"
|
||||
#include "storage/browser/blob/blob_url_loader_factory.h"
|
||||
@@ -58,9 +59,9 @@ class BlobURLTokenImpl : public blink::mojom::BlobURLToken {
|
||||
const base::UnguessableToken token_;
|
||||
};
|
||||
|
||||
-BlobURLStoreImpl::BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
|
||||
- BlobRegistryImpl::Delegate* delegate)
|
||||
- : registry_(std::move(registry)), delegate_(delegate) {}
|
||||
+BlobURLStoreImpl::BlobURLStoreImpl(const url::Origin& origin,
|
||||
+ base::WeakPtr<BlobUrlRegistry> registry)
|
||||
+ : origin_(origin), registry_(std::move(registry)) {}
|
||||
|
||||
BlobURLStoreImpl::~BlobURLStoreImpl() {
|
||||
if (registry_) {
|
||||
@@ -72,20 +73,9 @@ BlobURLStoreImpl::~BlobURLStoreImpl() {
|
||||
void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob,
|
||||
const GURL& url,
|
||||
RegisterCallback callback) {
|
||||
- if (!url.SchemeIsBlob()) {
|
||||
- mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Register");
|
||||
- std::move(callback).Run();
|
||||
- return;
|
||||
- }
|
||||
- if (!delegate_->CanCommitURL(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "Non committable URL passed to BlobURLStore::Register");
|
||||
- std::move(callback).Run();
|
||||
- return;
|
||||
- }
|
||||
- if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "URL with fragment passed to BlobURLStore::Register");
|
||||
+ // TODO(mek): Generate blob URLs here, rather than validating the URLs the
|
||||
+ // renderer process generated.
|
||||
+ if (!BlobUrlIsValid(url, "Register")) {
|
||||
std::move(callback).Run();
|
||||
return;
|
||||
}
|
||||
@@ -97,19 +87,8 @@ void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob,
|
||||
}
|
||||
|
||||
void BlobURLStoreImpl::Revoke(const GURL& url) {
|
||||
- if (!url.SchemeIsBlob()) {
|
||||
- mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Revoke");
|
||||
- return;
|
||||
- }
|
||||
- if (!delegate_->CanCommitURL(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "Non committable URL passed to BlobURLStore::Revoke");
|
||||
+ if (!BlobUrlIsValid(url, "Revoke"))
|
||||
return;
|
||||
- }
|
||||
- if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
- mojo::ReportBadMessage("URL with fragment passed to BlobURLStore::Revoke");
|
||||
- return;
|
||||
- }
|
||||
|
||||
if (registry_)
|
||||
registry_->RemoveUrlMapping(url);
|
||||
@@ -144,4 +123,38 @@ void BlobURLStoreImpl::ResolveForNavigation(
|
||||
new BlobURLTokenImpl(registry_, url, std::move(blob), std::move(token));
|
||||
}
|
||||
|
||||
+bool BlobURLStoreImpl::BlobUrlIsValid(const GURL& url,
|
||||
+ const char* method) const {
|
||||
+ if (!url.SchemeIsBlob()) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ base::StrCat({"Invalid scheme passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ url::Origin url_origin = url::Origin::Create(url);
|
||||
+ // For file:// origins blink sometimes creates blob URLs with "null" as origin
|
||||
+ // and other times "file://" (based on a runtime setting). On the other hand,
|
||||
+ // `origin_` will always be a non-opaque file: origin for pages loaded from
|
||||
+ // file:// URLs. To deal with this, we treat file:// origins and
|
||||
+ // opaque origins separately from non-opaque origins.
|
||||
+ bool valid_origin = true;
|
||||
+ if (url_origin.scheme() == url::kFileScheme) {
|
||||
+ valid_origin = origin_.scheme() == url::kFileScheme;
|
||||
+ } else if (url_origin.opaque()) {
|
||||
+ valid_origin = origin_.opaque() || origin_.scheme() == url::kFileScheme;
|
||||
+ } else {
|
||||
+ valid_origin = origin_ == url_origin;
|
||||
+ }
|
||||
+ if (!valid_origin) {
|
||||
+ mojo::ReportBadMessage(base::StrCat(
|
||||
+ {"URL with invalid origin passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ base::StrCat({"URL with fragment passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
} // namespace storage
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl.h b/storage/browser/blob/blob_url_store_impl.h
|
||||
index 6b4a738a4646f8d8e35e8bb1be5aba391e612917..5db371d7c6d50520d8b40a3b4cb6d6bbf920b570 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl.h
|
||||
+++ b/storage/browser/blob/blob_url_store_impl.h
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
-#include "storage/browser/blob/blob_registry_impl.h"
|
||||
+#include "storage/browser/blob/blob_url_registry.h"
|
||||
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
|
||||
+#include "url/origin.h"
|
||||
|
||||
namespace storage {
|
||||
|
||||
@@ -21,8 +22,9 @@ class BlobUrlRegistry;
|
||||
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
|
||||
: public blink::mojom::BlobURLStore {
|
||||
public:
|
||||
- BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
|
||||
- BlobRegistryImpl::Delegate* delegate);
|
||||
+ BlobURLStoreImpl(const url::Origin& origin,
|
||||
+ base::WeakPtr<BlobUrlRegistry> registry);
|
||||
+
|
||||
~BlobURLStoreImpl() override;
|
||||
|
||||
void Register(mojo::PendingRemote<blink::mojom::Blob> blob,
|
||||
@@ -39,8 +41,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
|
||||
mojo::PendingReceiver<blink::mojom::BlobURLToken> token) override;
|
||||
|
||||
private:
|
||||
+ // Checks if the passed in url is a valid blob url for this blob url store.
|
||||
+ // Returns false and reports a bad mojo message if not.
|
||||
+ bool BlobUrlIsValid(const GURL& url, const char* method) const;
|
||||
+
|
||||
+ const url::Origin origin_;
|
||||
base::WeakPtr<BlobUrlRegistry> registry_;
|
||||
- BlobRegistryImpl::Delegate* delegate_;
|
||||
|
||||
std::set<GURL> urls_;
|
||||
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
index b81232212472036878e0918523be17bb2c2a8b8a..4244890c48240769b1333492bb870420fa26b869 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
+++ b/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "storage/browser/blob/blob_impl.h"
|
||||
#include "storage/browser/blob/blob_storage_context.h"
|
||||
#include "storage/browser/blob/blob_url_registry.h"
|
||||
-#include "storage/browser/test/mock_blob_registry_delegate.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
using blink::mojom::BlobURLStore;
|
||||
@@ -70,9 +69,9 @@ class BlobURLStoreImplTest : public testing::Test {
|
||||
|
||||
mojo::PendingRemote<BlobURLStore> CreateURLStore() {
|
||||
mojo::PendingRemote<BlobURLStore> result;
|
||||
- mojo::MakeSelfOwnedReceiver(std::make_unique<BlobURLStoreImpl>(
|
||||
- url_registry_.AsWeakPtr(), &delegate_),
|
||||
- result.InitWithNewPipeAndPassReceiver());
|
||||
+ mojo::MakeSelfOwnedReceiver(
|
||||
+ std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr()),
|
||||
+ result.InitWithNewPipeAndPassReceiver());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -102,15 +101,19 @@ class BlobURLStoreImplTest : public testing::Test {
|
||||
}
|
||||
|
||||
const std::string kId = "id";
|
||||
- const GURL kValidUrl = GURL("blob:id");
|
||||
+ const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
|
||||
+ const GURL kValidUrl = GURL("blob:" + kOrigin.Serialize() + "/id1");
|
||||
+ const GURL kValidUrl2 = GURL("blob:" + kOrigin.Serialize() + "/id2");
|
||||
const GURL kInvalidUrl = GURL("bolb:id");
|
||||
- const GURL kFragmentUrl = GURL("blob:id#fragment");
|
||||
+ const GURL kFragmentUrl = GURL(kValidUrl.spec() + "#fragment");
|
||||
+ const url::Origin kWrongOrigin =
|
||||
+ url::Origin::Create(GURL("https://test.com"));
|
||||
+ const GURL kWrongOriginUrl = GURL("blob:" + kWrongOrigin.Serialize() + "/id");
|
||||
|
||||
protected:
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
std::unique_ptr<BlobStorageContext> context_;
|
||||
BlobUrlRegistry url_registry_;
|
||||
- MockBlobRegistryDelegate delegate_;
|
||||
std::vector<std::string> bad_messages_;
|
||||
};
|
||||
|
||||
@@ -119,7 +122,7 @@ TEST_F(BlobURLStoreImplTest, BasicRegisterRevoke) {
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
// Register a URL and make sure the URL keeps the blob alive.
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
blob = url_registry_.GetBlobFromUrl(kValidUrl);
|
||||
@@ -147,15 +150,13 @@ TEST_F(BlobURLStoreImplTest, RegisterInvalidScheme) {
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
-TEST_F(BlobURLStoreImplTest, RegisterCantCommit) {
|
||||
+TEST_F(BlobURLStoreImplTest, RegisterWrongOrigin) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- delegate_.can_commit_url_result = false;
|
||||
-
|
||||
mojo::Remote<BlobURLStore> url_store(CreateURLStore());
|
||||
- RegisterURL(url_store.get(), std::move(blob), kValidUrl);
|
||||
- EXPECT_FALSE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
+ RegisterURL(url_store.get(), std::move(blob), kWrongOriginUrl);
|
||||
+ EXPECT_FALSE(url_registry_.GetBlobFromUrl(kWrongOriginUrl));
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
@@ -170,14 +171,13 @@ TEST_F(BlobURLStoreImplTest, RegisterUrlFragment) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ImplicitRevoke) {
|
||||
- const GURL kValidUrl2("blob:id2");
|
||||
mojo::Remote<blink::mojom::Blob> blob(
|
||||
CreateBlobFromString(kId, "hello world"));
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob2;
|
||||
blob->Clone(blob2.InitWithNewPipeAndPassReceiver());
|
||||
|
||||
auto url_store =
|
||||
- std::make_unique<BlobURLStoreImpl>(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(url_store.get(), blob.Unbind(), kValidUrl);
|
||||
EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
RegisterURL(url_store.get(), std::move(blob2), kValidUrl2);
|
||||
@@ -193,8 +193,8 @@ TEST_F(BlobURLStoreImplTest, RevokeThroughDifferentURLStore) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store1(url_registry_.AsWeakPtr(), &delegate_);
|
||||
- BlobURLStoreImpl url_store2(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store1(kOrigin, url_registry_.AsWeakPtr());
|
||||
+ BlobURLStoreImpl url_store2(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
RegisterURL(&url_store1, std::move(blob), kValidUrl);
|
||||
EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
@@ -210,11 +210,9 @@ TEST_F(BlobURLStoreImplTest, RevokeInvalidScheme) {
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
-TEST_F(BlobURLStoreImplTest, RevokeCantCommit) {
|
||||
- delegate_.can_commit_url_result = false;
|
||||
-
|
||||
+TEST_F(BlobURLStoreImplTest, RevokeWrongOrigin) {
|
||||
mojo::Remote<BlobURLStore> url_store(CreateURLStore());
|
||||
- url_store->Revoke(kValidUrl);
|
||||
+ url_store->Revoke(kWrongOriginUrl);
|
||||
url_store.FlushForTesting();
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
@@ -230,7 +228,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
blob = ResolveURL(&url_store, kValidUrl);
|
||||
@@ -245,7 +243,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
ResolveURL(&url_store, kValidUrl);
|
||||
@@ -255,7 +253,7 @@ TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ResolveInvalidURL) {
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
ResolveURL(&url_store, kInvalidUrl);
|
||||
@@ -266,7 +264,7 @@ TEST_F(BlobURLStoreImplTest, ResolveAsURLLoaderFactory) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
mojo::Remote<network::mojom::URLLoaderFactory> factory;
|
||||
@@ -292,7 +290,7 @@ TEST_F(BlobURLStoreImplTest, ResolveForNavigation) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
mojo::Remote<blink::mojom::BlobURLToken> token_remote;
|
||||
67
patches/chromium/m98_fs_fix_fileutil_lifetime_issue.patch
Normal file
67
patches/chromium/m98_fs_fix_fileutil_lifetime_issue.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Thu, 10 Feb 2022 22:18:54 +0000
|
||||
Subject: M98: FS: Fix FileUtil lifetime issue
|
||||
|
||||
Keeps FileSystemContext alive while while resolving a URL on an open
|
||||
file system, removing the possibility of the file system being
|
||||
destroyed while a URL is being resolved on it.
|
||||
|
||||
(cherry picked from commit 3fdf2adf11b3c716c9015597d30b59bffc7ac91b)
|
||||
|
||||
Bug: 1275622, 1289394
|
||||
Change-Id: Ic1b97552f9d41a61163d72ff8c605699f673f55f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3373583
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#968470}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3451059
|
||||
Auto-Submit: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1131}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/storage/browser/file_system/file_system_context.cc b/storage/browser/file_system/file_system_context.cc
|
||||
index 4ae64d27f5ef446dca59b89b7fa8f652fb949bdc..f88aa4e0b3c0bf6c9cf25dada88d9af960409e7e 100644
|
||||
--- a/storage/browser/file_system/file_system_context.cc
|
||||
+++ b/storage/browser/file_system/file_system_context.cc
|
||||
@@ -418,9 +418,22 @@ void FileSystemContext::OpenFileSystem(const url::Origin& origin,
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Bind `this` to the callback to ensure this instance stays alive while the
|
||||
+ // URL is resolving.
|
||||
backend->ResolveURL(
|
||||
CreateCrackedFileSystemURL(origin, type, base::FilePath()), mode,
|
||||
- std::move(callback));
|
||||
+ base::BindOnce(&FileSystemContext::DidResolveURLOnOpenFileSystem, this,
|
||||
+ std::move(callback)));
|
||||
+}
|
||||
+
|
||||
+void FileSystemContext::DidResolveURLOnOpenFileSystem(
|
||||
+ OpenFileSystemCallback callback,
|
||||
+ const GURL& filesystem_root,
|
||||
+ const std::string& filesystem_name,
|
||||
+ base::File::Error error) {
|
||||
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
+
|
||||
+ std::move(callback).Run(filesystem_root, filesystem_name, error);
|
||||
}
|
||||
|
||||
void FileSystemContext::ResolveURL(const FileSystemURL& url,
|
||||
diff --git a/storage/browser/file_system/file_system_context.h b/storage/browser/file_system/file_system_context.h
|
||||
index 2f9b043f15b78c8e09bb4e6675bb5ef21fdac90c..789cecb8fd69ef39b050c229fd0668b7269f352b 100644
|
||||
--- a/storage/browser/file_system/file_system_context.h
|
||||
+++ b/storage/browser/file_system/file_system_context.h
|
||||
@@ -382,6 +382,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext
|
||||
const std::string& filesystem_name,
|
||||
base::File::Error error);
|
||||
|
||||
+ void DidResolveURLOnOpenFileSystem(OpenFileSystemCallback callback,
|
||||
+ const GURL& filesystem_root,
|
||||
+ const std::string& filesystem_name,
|
||||
+ base::File::Error error);
|
||||
+
|
||||
// Returns a FileSystemBackend, used only by test code.
|
||||
SandboxFileSystemBackend* sandbox_backend() const {
|
||||
return sandbox_backend_.get();
|
||||
157
patches/chromium/sandbox_fix_sandbox_inheritance_m96_merge.patch
Normal file
157
patches/chromium/sandbox_fix_sandbox_inheritance_m96_merge.patch
Normal file
@@ -0,0 +1,157 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Date: Wed, 3 Nov 2021 12:49:50 +0000
|
||||
Subject: sandbox: Fix sandbox inheritance [M96 merge]
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is a cherry-pick of the following patch:
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/3231298
|
||||
|
||||
Patch description:
|
||||
------------------
|
||||
When creating a new frame and the initial empty document, blink was only
|
||||
sending the frame's sandbox attribute, but without combining with its owner's
|
||||
(=document) sandbox flags.
|
||||
|
||||
This patch combines frame's attribute with its document sandbox flags.
|
||||
|
||||
🎁 Arthur Sonzogni wishes for a better future: 🎁
|
||||
-------------------------------------------------
|
||||
There are no good reasons sandbox flags inheritance to be complicated.
|
||||
See: content/browser/renderer_host/sandbox_flags.md
|
||||
|
||||
For legacy reasons, Chrome's developers were confused about what objects
|
||||
have frame or document semantic. On the browser process, the
|
||||
FrameTreeNode represents the frame and the RenderFrameHost is almost
|
||||
(%RenderDocument) the document/execution-context.
|
||||
|
||||
Currently, sandbox flags is plumbed inside FramePolicy, and it is not
|
||||
clear to me whether FramePolicy is a frame-scoped or document-scoped
|
||||
property (or both).
|
||||
The current logic speak about "pending" FramePolicy (=frame) and
|
||||
"active" FramePolicy (=document) and store both type into the
|
||||
FrameTreeNode and RenderFrameHost, which is not ideal.
|
||||
|
||||
I believe we should extract SandboxFlags outside of FramePolicy and
|
||||
make a very clean implementation, parallel to the PolicyContainer logic.
|
||||
In a second step it could also be integrated into PolicyContainer, if we
|
||||
resolve the additional property that sandbox flags can also be further
|
||||
restricted at the frame level, similar to CSP embedded enforcement.
|
||||
|
||||
Bug: 1256822, 1262061
|
||||
Change-Id: Id38de6d7eeeb1e4fa7722ab56288666763fae838
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3231298
|
||||
Commit-Queue: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Auto-Submit: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Reviewed-by: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Reviewed-by: Mike West <mkwst@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#933845}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3256558
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#695}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
|
||||
index 56f159a45c50e6db658ffd783bf01ea4d4e54988..de7d2cfd70fbc02499b1c3a2097f7340c2d01e0b 100644
|
||||
--- a/content/browser/bad_message.h
|
||||
+++ b/content/browser/bad_message.h
|
||||
@@ -275,6 +275,11 @@ enum BadMessageReason {
|
||||
MDDH_INVALID_PERMITTED_ORIGIN = 247,
|
||||
MDDH_NOT_TOP_LEVEL = 248,
|
||||
RFH_DID_CHANGE_IFRAME_ATTRIBUTE = 249,
|
||||
+ FARI_LOGOUT_BAD_ENDPOINT = 250,
|
||||
+ RFH_CHILD_FRAME_UNEXPECTED_OWNER_ELEMENT_TYPE = 251,
|
||||
+ RFH_POPUP_REQUEST_WHILE_PRERENDERING = 252,
|
||||
+ RFH_INTERECEPT_DOWNLOAD_WHILE_INACTIVE = 253, // Unused until 97.0.4674.0
|
||||
+ RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS = 254,
|
||||
|
||||
// Please add new elements here. The naming convention is abbreviated class
|
||||
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
|
||||
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
|
||||
index 7596d071d856b8b41ba8e7101f7fb032e3055334..6cf311deea370119bb1504e7f02c08c6757fa1da 100644
|
||||
--- a/content/browser/renderer_host/frame_tree_node.cc
|
||||
+++ b/content/browser/renderer_host/frame_tree_node.cc
|
||||
@@ -472,6 +472,12 @@ bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
|
||||
|
||||
bool FrameTreeNode::CommitFramePolicy(
|
||||
const blink::FramePolicy& new_frame_policy) {
|
||||
+ // Documents create iframes, iframes host new documents. Both are associated
|
||||
+ // with sandbox flags. They are required to be stricter or equal to their
|
||||
+ // owner when they change, as we go down.
|
||||
+ // TODO(https://crbug.com/1262061). Enforce the invariant mentioned above,
|
||||
+ // once the interactions with FencedIframe has been tested and clarified.
|
||||
+
|
||||
bool did_change_flags = new_frame_policy.sandbox_flags !=
|
||||
replication_state_->frame_policy.sandbox_flags;
|
||||
bool did_change_container_policy =
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 10f34740cad12975914107a9c07bdbe9279120aa..1077dc1ef688c7dcea8dc85f006eae4560c9115a 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -3506,6 +3506,16 @@ void RenderFrameHostImpl::CreateChildFrame(
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Documents create iframes, iframes host new documents. Both are associated
|
||||
+ // with sandbox flags. They are required to be stricter or equal to their
|
||||
+ // owner when they are created, as we go down.
|
||||
+ if (frame_policy.sandbox_flags !=
|
||||
+ (frame_policy.sandbox_flags | active_sandbox_flags())) {
|
||||
+ bad_message::ReceivedBadMessage(
|
||||
+ GetProcess(), bad_message::RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// TODO(crbug.com/1145708). The interface exposed to tests should
|
||||
// match the mojo interface.
|
||||
OnCreateChildFrame(new_routing_id, std::move(frame_remote),
|
||||
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
index 1ffff24a749e37552ad771061c9cef68568df784..2be62c3b5ef9f192dd5652e432b81adf71aa067c 100644
|
||||
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
|
||||
@@ -2113,6 +2113,16 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
|
||||
policy_container_receiver =
|
||||
policy_container_remote.InitWithNewEndpointAndPassReceiver();
|
||||
|
||||
+ FramePolicy frame_policy = owner_element->GetFramePolicy();
|
||||
+ // Documents create iframes, iframes host new documents. Both are associated
|
||||
+ // with sandbox flags. They are required to be stricter or equal as we go
|
||||
+ // down. The iframe owner element only returns the additional restrictions
|
||||
+ // defined in the HTMLIFrameElement's sanbox attribute. It needs to be
|
||||
+ // combined with the document's sandbox flags to get the frame's sandbox
|
||||
+ // policy right.
|
||||
+ frame_policy.sandbox_flags |=
|
||||
+ GetFrame()->GetDocument()->GetExecutionContext()->GetSandboxFlags();
|
||||
+
|
||||
// FIXME: Using subResourceAttributeName as fallback is not a perfect
|
||||
// solution. subResourceAttributeName returns just one attribute name. The
|
||||
// element might not have the attribute, and there might be other attributes
|
||||
@@ -2122,8 +2132,7 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
|
||||
scope, name,
|
||||
owner_element->getAttribute(
|
||||
owner_element->SubResourceAttributeName()),
|
||||
- owner_element->GetFramePolicy(), owner_properties,
|
||||
- owner_element->OwnerType(),
|
||||
+ std::move(frame_policy), owner_properties, owner_element->OwnerType(),
|
||||
WebPolicyContainerBindParams{std::move(policy_container_receiver)}));
|
||||
if (!webframe_child)
|
||||
return nullptr;
|
||||
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
|
||||
index 521f49669eef1ed5fe445618984c3c93fb70d786..8e8bffa245e752f0941e2419da1db0cf365d0f50 100644
|
||||
--- a/tools/metrics/histograms/enums.xml
|
||||
+++ b/tools/metrics/histograms/enums.xml
|
||||
@@ -7589,6 +7589,11 @@ Called by update_bad_message_reasons.py.-->
|
||||
<int value="247" label="MDDH_INVALID_PERMITTED_ORIGIN"/>
|
||||
<int value="248" label="MDDH_NOT_TOP_LEVEL"/>
|
||||
<int value="249" label="RFH_DID_CHANGE_IFRAME_ATTRIBUTE"/>
|
||||
+ <int value="250" label="FARI_LOGOUT_BAD_ENDPOINT"/>
|
||||
+ <int value="251" label="RFH_CHILD_FRAME_UNEXPECTED_OWNER_ELEMENT_TYPE"/>
|
||||
+ <int value="252" label="RFH_POPUP_REQUEST_WHILE_PRERENDERING"/>
|
||||
+ <int value="253" label="RFH_INTERECEPT_DOWNLOAD_WHILE_INACTIVE"/>
|
||||
+ <int value="254" label="RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS"/>
|
||||
</enum>
|
||||
|
||||
<enum name="BadMessageReasonExtensions">
|
||||
@@ -15,3 +15,7 @@ merged_cppgc_fix_marking_of_ephemerons_with_keys_in_construction.patch
|
||||
cherry-pick-014e1f857c33.patch
|
||||
cherry-pick-feef10137b16.patch
|
||||
cherry-pick-5d2b5e7c006c.patch
|
||||
merged_allow_compiled_module_invalidation_at_wasmstreaming_finish.patch
|
||||
version_9_6_180_13_cherry-pick.patch
|
||||
cherry-pick-418c276ef228.patch
|
||||
cherry-pick-27bc67f761e6.patch
|
||||
|
||||
253
patches/v8/cherry-pick-27bc67f761e6.patch
Normal file
253
patches/v8/cherry-pick-27bc67f761e6.patch
Normal file
@@ -0,0 +1,253 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakob Gruber <jgruber@chromium.org>
|
||||
Date: Thu, 13 Jan 2022 08:01:37 +0100
|
||||
Subject: Merged: [maps] Lock map_updater_access in
|
||||
CompleteInobjectSlackTracking
|
||||
|
||||
CompleteInobjectSlackTracking potentially shrinks multiple maps, and
|
||||
the relation between these maps should be preserved in a concurrent
|
||||
environment. Thus it is not enough to make each modification
|
||||
atomically, but all related map modifications must be within a
|
||||
critical section.
|
||||
|
||||
We do this by locking the map_updater_access mutex
|
||||
CompleteInobjectSlackTracking, and hence moving the function to the
|
||||
MapUpdater class.
|
||||
|
||||
(cherry picked from commit 4b8d04897cba70cac45eea33d78fa2354dfe2bd7)
|
||||
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Treechecks: true
|
||||
Bug: chromium:1274445,v8:7990
|
||||
Change-Id: If99bb8b55e03180128ee397d845fa4c269c4241e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3379819
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#78597}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3406537
|
||||
Cr-Commit-Position: refs/branch-heads/9.8@{#16}
|
||||
Cr-Branched-From: e218afa8473132b56a9e1532be7920dd130aeb7e-refs/heads/9.8.177@{#1}
|
||||
Cr-Branched-From: 86ebfc969cde382122a4d429f2380f06175ea2a8-refs/heads/main@{#78312}
|
||||
|
||||
diff --git a/src/objects/js-function-inl.h b/src/objects/js-function-inl.h
|
||||
index bae63f6ef9672958914ce4daaf41e948b7b0697d..7fdc6f1b93942df03d3eb61147f2c2e22e4de984 100644
|
||||
--- a/src/objects/js-function-inl.h
|
||||
+++ b/src/objects/js-function-inl.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "src/ic/ic.h"
|
||||
#include "src/init/bootstrapper.h"
|
||||
#include "src/objects/feedback-cell-inl.h"
|
||||
+#include "src/objects/map-updater.h"
|
||||
#include "src/objects/shared-function-info-inl.h"
|
||||
|
||||
// Has to be the last include (doesn't have include guards):
|
||||
@@ -126,7 +127,7 @@ bool JSFunction::IsInOptimizationQueue() {
|
||||
void JSFunction::CompleteInobjectSlackTrackingIfActive() {
|
||||
if (!has_prototype_slot()) return;
|
||||
if (has_initial_map() && initial_map().IsInobjectSlackTrackingInProgress()) {
|
||||
- initial_map().CompleteInobjectSlackTracking(GetIsolate());
|
||||
+ MapUpdater::CompleteInobjectSlackTracking(GetIsolate(), initial_map());
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/objects/map-inl.h b/src/objects/map-inl.h
|
||||
index d170341b9a05c7d0ae555713bcd1a671be4642e9..8afafc0a8a5b79e89a65ac286c331afecc5a5568 100644
|
||||
--- a/src/objects/map-inl.h
|
||||
+++ b/src/objects/map-inl.h
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "src/objects/field-type.h"
|
||||
#include "src/objects/instance-type-inl.h"
|
||||
#include "src/objects/js-function-inl.h"
|
||||
+#include "src/objects/map-updater.h"
|
||||
#include "src/objects/map.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/property.h"
|
||||
@@ -828,7 +829,7 @@ void Map::InobjectSlackTrackingStep(Isolate* isolate) {
|
||||
int counter = construction_counter();
|
||||
set_construction_counter(counter - 1);
|
||||
if (counter == kSlackTrackingCounterEnd) {
|
||||
- CompleteInobjectSlackTracking(isolate);
|
||||
+ MapUpdater::CompleteInobjectSlackTracking(isolate, *this);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/objects/map-updater.cc b/src/objects/map-updater.cc
|
||||
index feb060fa5184e1533895b41989b8e35109036f6a..3ed7fa3af1a7aec18fbe77997a76f1ce01c33ebb 100644
|
||||
--- a/src/objects/map-updater.cc
|
||||
+++ b/src/objects/map-updater.cc
|
||||
@@ -301,21 +301,50 @@ MapUpdater::State MapUpdater::Normalize(const char* reason) {
|
||||
return state_; // Done.
|
||||
}
|
||||
|
||||
-void MapUpdater::ShrinkInstanceSize(base::SharedMutex* map_updater_access,
|
||||
- Map map, int slack) {
|
||||
+// static
|
||||
+void MapUpdater::CompleteInobjectSlackTracking(Isolate* isolate,
|
||||
+ Map initial_map) {
|
||||
+ DisallowGarbageCollection no_gc;
|
||||
+ // Has to be an initial map.
|
||||
+ DCHECK(initial_map.GetBackPointer().IsUndefined(isolate));
|
||||
+
|
||||
+ const int slack = initial_map.ComputeMinObjectSlack(isolate);
|
||||
DCHECK_GE(slack, 0);
|
||||
+
|
||||
+ TransitionsAccessor transitions(isolate, initial_map, &no_gc);
|
||||
+ TransitionsAccessor::TraverseCallback callback;
|
||||
+ if (slack != 0) {
|
||||
+ // Resize the initial map and all maps in its transition tree.
|
||||
+ callback = [slack](Map map) {
|
||||
#ifdef DEBUG
|
||||
- int old_visitor_id = Map::GetVisitorId(map);
|
||||
- int new_unused = map.UnusedPropertyFields() - slack;
|
||||
+ int old_visitor_id = Map::GetVisitorId(map);
|
||||
+ int new_unused = map.UnusedPropertyFields() - slack;
|
||||
#endif
|
||||
+ map.set_instance_size(map.InstanceSizeFromSlack(slack));
|
||||
+ map.set_construction_counter(Map::kNoSlackTracking);
|
||||
+ DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
|
||||
+ DCHECK_EQ(new_unused, map.UnusedPropertyFields());
|
||||
+ };
|
||||
+ } else {
|
||||
+ // Stop slack tracking for this map.
|
||||
+ callback = [](Map map) {
|
||||
+ map.set_construction_counter(Map::kNoSlackTracking);
|
||||
+ };
|
||||
+ }
|
||||
|
||||
{
|
||||
- base::SharedMutexGuard<base::kExclusive> mutex_guard(map_updater_access);
|
||||
- map.set_instance_size(map.InstanceSizeFromSlack(slack));
|
||||
+ // The map_updater_access lock is taken here to guarantee atomicity of all
|
||||
+ // related map changes (instead of guaranteeing only atomicity of each
|
||||
+ // single map change). This is needed e.g. by InstancesNeedsRewriting,
|
||||
+ // which expects certain relations between maps to hold.
|
||||
+ //
|
||||
+ // Note: Avoid locking the full_transition_array_access lock inside this
|
||||
+ // call to TraverseTransitionTree to prevent dependencies between the two
|
||||
+ // locks.
|
||||
+ base::SharedMutexGuard<base::kExclusive> mutex_guard(
|
||||
+ isolate->map_updater_access());
|
||||
+ transitions.TraverseTransitionTree(callback);
|
||||
}
|
||||
- map.set_construction_counter(Map::kNoSlackTracking);
|
||||
- DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
|
||||
- DCHECK_EQ(new_unused, map.UnusedPropertyFields());
|
||||
}
|
||||
|
||||
MapUpdater::State MapUpdater::TryReconfigureToDataFieldInplace() {
|
||||
diff --git a/src/objects/map-updater.h b/src/objects/map-updater.h
|
||||
index c901782bf176600aa08df210d55301045d4b5e2e..2fc66d0c3709b87ea0e7aa96a2943eea4ecefc6e 100644
|
||||
--- a/src/objects/map-updater.h
|
||||
+++ b/src/objects/map-updater.h
|
||||
@@ -80,8 +80,9 @@ class V8_EXPORT_PRIVATE MapUpdater {
|
||||
Representation new_representation,
|
||||
Handle<FieldType> new_field_type);
|
||||
|
||||
- static void ShrinkInstanceSize(base::SharedMutex* map_updater_access, Map map,
|
||||
- int slack);
|
||||
+ // Completes inobject slack tracking for the transition tree starting at the
|
||||
+ // initial map.
|
||||
+ static void CompleteInobjectSlackTracking(Isolate* isolate, Map initial_map);
|
||||
|
||||
private:
|
||||
enum State {
|
||||
diff --git a/src/objects/map.cc b/src/objects/map.cc
|
||||
index 50d5728b0e13edf4f1052f2014f9e32c4056a512..84b2444ca2d61a8b4300ff30bd6ab2a93448ad60 100644
|
||||
--- a/src/objects/map.cc
|
||||
+++ b/src/objects/map.cc
|
||||
@@ -2200,28 +2200,6 @@ int Map::ComputeMinObjectSlack(Isolate* isolate) {
|
||||
return slack;
|
||||
}
|
||||
|
||||
-void Map::CompleteInobjectSlackTracking(Isolate* isolate) {
|
||||
- DisallowGarbageCollection no_gc;
|
||||
- // Has to be an initial map.
|
||||
- DCHECK(GetBackPointer().IsUndefined(isolate));
|
||||
-
|
||||
- int slack = ComputeMinObjectSlack(isolate);
|
||||
- TransitionsAccessor transitions(isolate, *this, &no_gc);
|
||||
- TransitionsAccessor::TraverseCallback callback;
|
||||
- if (slack != 0) {
|
||||
- // Resize the initial map and all maps in its transition tree.
|
||||
- callback = [&](Map map) {
|
||||
- MapUpdater::ShrinkInstanceSize(isolate->map_updater_access(), map, slack);
|
||||
- };
|
||||
- } else {
|
||||
- callback = [](Map map) {
|
||||
- // Stop slack tracking for this map.
|
||||
- map.set_construction_counter(Map::kNoSlackTracking);
|
||||
- };
|
||||
- }
|
||||
- transitions.TraverseTransitionTree(callback);
|
||||
-}
|
||||
-
|
||||
void Map::SetInstanceDescriptors(Isolate* isolate, DescriptorArray descriptors,
|
||||
int number_of_own_descriptors) {
|
||||
set_instance_descriptors(descriptors, kReleaseStore);
|
||||
diff --git a/src/objects/map.h b/src/objects/map.h
|
||||
index 355d86a332412a3e1c24cdf5ad866cc8871ba4f1..16435e4a3507d93c832e0cd77cf82535d3d51938 100644
|
||||
--- a/src/objects/map.h
|
||||
+++ b/src/objects/map.h
|
||||
@@ -352,10 +352,6 @@ class Map : public HeapObject {
|
||||
int ComputeMinObjectSlack(Isolate* isolate);
|
||||
inline int InstanceSizeFromSlack(int slack) const;
|
||||
|
||||
- // Completes inobject slack tracking for the transition tree starting at this
|
||||
- // initial map.
|
||||
- V8_EXPORT_PRIVATE void CompleteInobjectSlackTracking(Isolate* isolate);
|
||||
-
|
||||
// Tells whether the object in the prototype property will be used
|
||||
// for instances created from this function. If the prototype
|
||||
// property is set to a value that is not a JSObject, the prototype
|
||||
diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc
|
||||
index 42bbb10d92e90640d2a7f61beba758cb752ae87b..add7cd191064686396de76912c5799d9bb3d487b 100644
|
||||
--- a/src/runtime/runtime-object.cc
|
||||
+++ b/src/runtime/runtime-object.cc
|
||||
@@ -1002,7 +1002,7 @@ RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTrackingForMap) {
|
||||
DCHECK_EQ(1, args.length());
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
|
||||
- initial_map->CompleteInobjectSlackTracking(isolate);
|
||||
+ MapUpdater::CompleteInobjectSlackTracking(isolate, *initial_map);
|
||||
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
diff --git a/src/runtime/runtime-test.cc b/src/runtime/runtime-test.cc
|
||||
index fb5949e2c90966a240ccfb1b61a01017a816f313..6c1df05ca95feb3f40db70f652a55b59450aa6aa 100644
|
||||
--- a/src/runtime/runtime-test.cc
|
||||
+++ b/src/runtime/runtime-test.cc
|
||||
@@ -1274,7 +1274,7 @@ RUNTIME_FUNCTION(Runtime_CompleteInobjectSlackTracking) {
|
||||
DCHECK_EQ(1, args.length());
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
||||
- object->map().CompleteInobjectSlackTracking(isolate);
|
||||
+ MapUpdater::CompleteInobjectSlackTracking(isolate, object->map());
|
||||
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
|
||||
index 5a12729d929a36fbcc89d0d2586c0cbfee72309c..f6373286cf99176b440db6965e657580321a6380 100644
|
||||
--- a/test/cctest/test-api.cc
|
||||
+++ b/test/cctest/test-api.cc
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/js-promise-inl.h"
|
||||
#include "src/objects/lookup.h"
|
||||
+#include "src/objects/map-updater.h"
|
||||
#include "src/objects/module-inl.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/string-inl.h"
|
||||
@@ -2972,9 +2973,9 @@ TEST(InternalFieldsSubclassing) {
|
||||
CHECK_LE(i_value->map().GetInObjectProperties(), kMaxNofProperties);
|
||||
}
|
||||
|
||||
- // Make Sure we get the precise property count.
|
||||
- i_value->map().FindRootMap(i_isolate).CompleteInobjectSlackTracking(
|
||||
- i_isolate);
|
||||
+ // Make sure we get the precise property count.
|
||||
+ i::MapUpdater::CompleteInobjectSlackTracking(
|
||||
+ i_isolate, i_value->map().FindRootMap(i_isolate));
|
||||
// TODO(cbruni): fix accounting to make this condition true.
|
||||
// CHECK_EQ(0, i_value->map()->UnusedPropertyFields());
|
||||
if (in_object_only) {
|
||||
40
patches/v8/cherry-pick-418c276ef228.patch
Normal file
40
patches/v8/cherry-pick-418c276ef228.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leszek Swirski <leszeks@chromium.org>
|
||||
Date: Fri, 10 Dec 2021 15:56:05 +0100
|
||||
Subject: Merged: [compiler] Don't elide
|
||||
ChangeTaggedToInt32->ChangeInt31ToTaggedSigned
|
||||
|
||||
(cherry picked from commit 4fae8b16802a416fe3aab0e7792fabe96cf1ecd8)
|
||||
|
||||
(cherry picked from commit f4f11c23ae2eaf9bb4525d0fac7ab842de9b0fe2)
|
||||
|
||||
Bug: chromium:1278387
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: I9b89834c094510e064988aa534ec230309996034
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3329665
|
||||
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/9.6@{#40}
|
||||
Cr-Original-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
|
||||
Cr-Original-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3335759
|
||||
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
|
||||
Owners-Override: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/9.4@{#56}
|
||||
Cr-Branched-From: 3b51863bc25492549a8bf96ff67ce481b1a3337b-refs/heads/9.4.146@{#1}
|
||||
Cr-Branched-From: 2890419fc8fb9bdb507fdd801d76fa7dd9f022b5-refs/heads/master@{#76233}
|
||||
|
||||
diff --git a/src/compiler/simplified-operator-reducer.cc b/src/compiler/simplified-operator-reducer.cc
|
||||
index ea9e9f4ba5dbc89d2f9d700d1a1111b9dda83e15..33edd66b4ff43e4150895bf232d107060876ca08 100644
|
||||
--- a/src/compiler/simplified-operator-reducer.cc
|
||||
+++ b/src/compiler/simplified-operator-reducer.cc
|
||||
@@ -77,7 +77,7 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
|
||||
case IrOpcode::kChangeInt32ToTagged: {
|
||||
Int32Matcher m(node->InputAt(0));
|
||||
if (m.HasResolvedValue()) return ReplaceNumber(m.ResolvedValue());
|
||||
- if (m.IsChangeTaggedToInt32() || m.IsChangeTaggedSignedToInt32()) {
|
||||
+ if (m.IsChangeTaggedSignedToInt32()) {
|
||||
return Replace(m.InputAt(0));
|
||||
}
|
||||
break;
|
||||
@@ -0,0 +1,181 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hiroshige Hayashizaki <hiroshige@chromium.org>
|
||||
Date: Tue, 23 Nov 2021 22:32:18 +0900
|
||||
Subject: Merged: Allow compiled module invalidation at WasmStreaming::Finish()
|
||||
|
||||
This CL adds `can_use_compiled_module` parameter to
|
||||
WasmStreaming::Finish() that is used by Chromium
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/3282643
|
||||
to invalidate compiled module bytes after SetCompiledModuleBytes().
|
||||
|
||||
(cherry picked from commit b0c6dd86bd563672dba6256f482dc5e145f094ae)
|
||||
|
||||
Bug: chromium:1260939
|
||||
Change-Id: I28554ed79ed56349fa38517ed03785e0c8146b4d
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3306788
|
||||
Commit-Queue: Hiroshige Hayashizaki <hiroshige@chromium.org>
|
||||
Reviewed-by: Andreas Haas <ahaas@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/9.6@{#36}
|
||||
Cr-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
|
||||
Cr-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
|
||||
|
||||
diff --git a/include/v8.h b/include/v8.h
|
||||
index 28ee5e6b673ce8f34d26a322cc83abc959f25c97..f74f1b88c01af72eb4ad6f795c48a028a1904e68 100644
|
||||
--- a/include/v8.h
|
||||
+++ b/include/v8.h
|
||||
@@ -5165,8 +5165,12 @@ class V8_EXPORT WasmStreaming final {
|
||||
* {Finish} should be called after all received bytes where passed to
|
||||
* {OnBytesReceived} to tell V8 that there will be no more bytes. {Finish}
|
||||
* does not have to be called after {Abort} has been called already.
|
||||
+ * If {can_use_compiled_module} is true and {SetCompiledModuleBytes} was
|
||||
+ * previously called, the compiled module bytes can be used.
|
||||
+ * If {can_use_compiled_module} is false, the compiled module bytes previously
|
||||
+ * set by {SetCompiledModuleBytes} should not be used.
|
||||
*/
|
||||
- void Finish();
|
||||
+ void Finish(bool can_use_compiled_module = true);
|
||||
|
||||
/**
|
||||
* Abort streaming compilation. If {exception} has a value, then the promise
|
||||
@@ -5181,6 +5185,8 @@ class V8_EXPORT WasmStreaming final {
|
||||
* can be used, false otherwise. The buffer passed via {bytes} and {size}
|
||||
* is owned by the caller. If {SetCompiledModuleBytes} returns true, the
|
||||
* buffer must remain valid until either {Finish} or {Abort} completes.
|
||||
+ * The compiled module bytes should not be used until {Finish(true)} is
|
||||
+ * called, because they can be invalidated later by {Finish(false)}.
|
||||
*/
|
||||
bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size);
|
||||
|
||||
diff --git a/src/api/api.cc b/src/api/api.cc
|
||||
index cc8a5b2a531de56daa35c6f35739401003be1f95..9b1349308d84b987efee7cca02a7b35fceb355fd 100644
|
||||
--- a/src/api/api.cc
|
||||
+++ b/src/api/api.cc
|
||||
@@ -10074,7 +10074,7 @@ void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
-void WasmStreaming::Finish() { UNREACHABLE(); }
|
||||
+void WasmStreaming::Finish(bool can_use_compiled_module) { UNREACHABLE(); }
|
||||
|
||||
void WasmStreaming::Abort(MaybeLocal<Value> exception) { UNREACHABLE(); }
|
||||
|
||||
diff --git a/src/wasm/streaming-decoder.cc b/src/wasm/streaming-decoder.cc
|
||||
index 22bc7d259a5f9ab84831bfe904fbec683c43e6de..639f4695c4df8012bc92556437e8bcd1a04e64f1 100644
|
||||
--- a/src/wasm/streaming-decoder.cc
|
||||
+++ b/src/wasm/streaming-decoder.cc
|
||||
@@ -35,7 +35,7 @@ class V8_EXPORT_PRIVATE AsyncStreamingDecoder : public StreamingDecoder {
|
||||
// The buffer passed into OnBytesReceived is owned by the caller.
|
||||
void OnBytesReceived(base::Vector<const uint8_t> bytes) override;
|
||||
|
||||
- void Finish() override;
|
||||
+ void Finish(bool can_use_compiled_module) override;
|
||||
|
||||
void Abort() override;
|
||||
|
||||
@@ -258,7 +258,7 @@ size_t AsyncStreamingDecoder::DecodingState::ReadBytes(
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
-void AsyncStreamingDecoder::Finish() {
|
||||
+void AsyncStreamingDecoder::Finish(bool can_use_compiled_module) {
|
||||
TRACE_STREAMING("Finish\n");
|
||||
DCHECK(!stream_finished_);
|
||||
stream_finished_ = true;
|
||||
@@ -268,9 +268,12 @@ void AsyncStreamingDecoder::Finish() {
|
||||
base::Vector<const uint8_t> wire_bytes =
|
||||
base::VectorOf(wire_bytes_for_deserializing_);
|
||||
// Try to deserialize the module from wire bytes and module bytes.
|
||||
- if (processor_->Deserialize(compiled_module_bytes_, wire_bytes)) return;
|
||||
+ if (can_use_compiled_module &&
|
||||
+ processor_->Deserialize(compiled_module_bytes_, wire_bytes))
|
||||
+ return;
|
||||
|
||||
- // Deserialization failed. Restart decoding using |wire_bytes|.
|
||||
+ // Compiled module bytes are invalidated by can_use_compiled_module = false
|
||||
+ // or the deserialization failed. Restart decoding using |wire_bytes|.
|
||||
compiled_module_bytes_ = {};
|
||||
DCHECK(!deserializing());
|
||||
OnBytesReceived(wire_bytes);
|
||||
diff --git a/src/wasm/streaming-decoder.h b/src/wasm/streaming-decoder.h
|
||||
index 2c5e1eae3c0a13f1a86c99cfb3a8696732697f36..6f4601b9f47170175703b150007919898199da92 100644
|
||||
--- a/src/wasm/streaming-decoder.h
|
||||
+++ b/src/wasm/streaming-decoder.h
|
||||
@@ -78,7 +78,7 @@ class V8_EXPORT_PRIVATE StreamingDecoder {
|
||||
// The buffer passed into OnBytesReceived is owned by the caller.
|
||||
virtual void OnBytesReceived(base::Vector<const uint8_t> bytes) = 0;
|
||||
|
||||
- virtual void Finish() = 0;
|
||||
+ virtual void Finish(bool can_use_compiled_module = true) = 0;
|
||||
|
||||
virtual void Abort() = 0;
|
||||
|
||||
@@ -96,6 +96,7 @@ class V8_EXPORT_PRIVATE StreamingDecoder {
|
||||
}
|
||||
|
||||
// Passes previously compiled module bytes from the embedder's cache.
|
||||
+ // The content shouldn't be used until Finish(true) is called.
|
||||
bool SetCompiledModuleBytes(
|
||||
base::Vector<const uint8_t> compiled_module_bytes) {
|
||||
compiled_module_bytes_ = compiled_module_bytes;
|
||||
@@ -124,6 +125,8 @@ class V8_EXPORT_PRIVATE StreamingDecoder {
|
||||
|
||||
std::string url_;
|
||||
ModuleCompiledCallback module_compiled_callback_;
|
||||
+ // The content of `compiled_module_bytes_` shouldn't be used until
|
||||
+ // Finish(true) is called.
|
||||
base::Vector<const uint8_t> compiled_module_bytes_;
|
||||
};
|
||||
|
||||
diff --git a/src/wasm/sync-streaming-decoder.cc b/src/wasm/sync-streaming-decoder.cc
|
||||
index 73c22cb5a32655fcb0f53145a03deaa79cb3b4a8..ebe1ead525edccf23d463e3cdfe4be7b3f2100c4 100644
|
||||
--- a/src/wasm/sync-streaming-decoder.cc
|
||||
+++ b/src/wasm/sync-streaming-decoder.cc
|
||||
@@ -32,7 +32,7 @@ class V8_EXPORT_PRIVATE SyncStreamingDecoder : public StreamingDecoder {
|
||||
buffer_size_ += bytes.size();
|
||||
}
|
||||
|
||||
- void Finish() override {
|
||||
+ void Finish(bool can_use_compiled_module) override {
|
||||
// We copy all received chunks into one byte buffer.
|
||||
auto bytes = std::make_unique<uint8_t[]>(buffer_size_);
|
||||
uint8_t* destination = bytes.get();
|
||||
@@ -43,7 +43,7 @@ class V8_EXPORT_PRIVATE SyncStreamingDecoder : public StreamingDecoder {
|
||||
CHECK_EQ(destination - bytes.get(), buffer_size_);
|
||||
|
||||
// Check if we can deserialize the module from cache.
|
||||
- if (deserializing()) {
|
||||
+ if (can_use_compiled_module && deserializing()) {
|
||||
HandleScope scope(isolate_);
|
||||
SaveAndSwitchContext saved_context(isolate_, *context_);
|
||||
|
||||
diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc
|
||||
index a452e51855db2e7ec335bf56975204c6299020c1..94ba36c1ec875a6a2832fadfcf191c9f9b57b9b6 100644
|
||||
--- a/src/wasm/wasm-js.cc
|
||||
+++ b/src/wasm/wasm-js.cc
|
||||
@@ -57,7 +57,9 @@ class WasmStreaming::WasmStreamingImpl {
|
||||
void OnBytesReceived(const uint8_t* bytes, size_t size) {
|
||||
streaming_decoder_->OnBytesReceived(base::VectorOf(bytes, size));
|
||||
}
|
||||
- void Finish() { streaming_decoder_->Finish(); }
|
||||
+ void Finish(bool can_use_compiled_module) {
|
||||
+ streaming_decoder_->Finish(can_use_compiled_module);
|
||||
+ }
|
||||
|
||||
void Abort(MaybeLocal<Value> exception) {
|
||||
i::HandleScope scope(reinterpret_cast<i::Isolate*>(isolate_));
|
||||
@@ -110,9 +112,9 @@ void WasmStreaming::OnBytesReceived(const uint8_t* bytes, size_t size) {
|
||||
impl_->OnBytesReceived(bytes, size);
|
||||
}
|
||||
|
||||
-void WasmStreaming::Finish() {
|
||||
+void WasmStreaming::Finish(bool can_use_compiled_module) {
|
||||
TRACE_EVENT0("v8.wasm", "wasm.FinishStreaming");
|
||||
- impl_->Finish();
|
||||
+ impl_->Finish(can_use_compiled_module);
|
||||
}
|
||||
|
||||
void WasmStreaming::Abort(MaybeLocal<Value> exception) {
|
||||
103
patches/v8/version_9_6_180_13_cherry-pick.patch
Normal file
103
patches/v8/version_9_6_180_13_cherry-pick.patch
Normal file
@@ -0,0 +1,103 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Leszek Swirski <leszeks@google.com>
|
||||
Date: Fri, 19 Nov 2021 12:12:03 +0100
|
||||
Subject: Version 9.6.180.13 (cherry-pick)
|
||||
|
||||
Merged 85ab0ad7789a7188b4c0b2be3cd3d758134c7de6
|
||||
|
||||
Reland "[runtime] Reset clobbered argument in DefineClass"
|
||||
|
||||
R=ishell@chromium.org
|
||||
|
||||
Change-Id: I892729eafe841e57b853f0d0a885e05847efe547
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3289176
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/9.6@{#24}
|
||||
Cr-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
|
||||
Cr-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
|
||||
|
||||
diff --git a/include/v8-version.h b/include/v8-version.h
|
||||
index 30a4182357505dcffcba3687964f6cb31942f6c9..52c772822e96104ba6dc75901d8c0eb4e3b46119 100644
|
||||
--- a/include/v8-version.h
|
||||
+++ b/include/v8-version.h
|
||||
@@ -11,7 +11,7 @@
|
||||
#define V8_MAJOR_VERSION 9
|
||||
#define V8_MINOR_VERSION 3
|
||||
#define V8_BUILD_NUMBER 345
|
||||
-#define V8_PATCH_LEVEL 19
|
||||
+#define V8_PATCH_LEVEL 20
|
||||
|
||||
// Use 1 for candidates and 0 otherwise.
|
||||
// (Boolean macro values are not supported by all preprocessors.)
|
||||
diff --git a/src/execution/arguments-inl.h b/src/execution/arguments-inl.h
|
||||
index 0be2325837189d48e3aae36fb611f7fa67041a31..2f69cd7adc4107e3dcc0dc012a3cffb55b9fa05e 100644
|
||||
--- a/src/execution/arguments-inl.h
|
||||
+++ b/src/execution/arguments-inl.h
|
||||
@@ -14,6 +14,15 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
+template <ArgumentsType T>
|
||||
+Arguments<T>::ChangeValueScope::ChangeValueScope(Isolate* isolate,
|
||||
+ Arguments* args, int index,
|
||||
+ Object value)
|
||||
+ : location_(args->address_of_arg_at(index)) {
|
||||
+ old_value_ = handle(Object(*location_), isolate);
|
||||
+ *location_ = value.ptr();
|
||||
+}
|
||||
+
|
||||
template <ArgumentsType T>
|
||||
int Arguments<T>::smi_at(int index) const {
|
||||
return Smi::ToInt(Object(*address_of_arg_at(index)));
|
||||
diff --git a/src/execution/arguments.h b/src/execution/arguments.h
|
||||
index 9ba80a401f78be4d90896c3ac3f5c82eaf8ea268..e1cd8d8c5f8af846fc710f8770cb349d49fd7306 100644
|
||||
--- a/src/execution/arguments.h
|
||||
+++ b/src/execution/arguments.h
|
||||
@@ -33,6 +33,18 @@ namespace internal {
|
||||
template <ArgumentsType arguments_type>
|
||||
class Arguments {
|
||||
public:
|
||||
+ // Scope to temporarily change the value of an argument.
|
||||
+ class ChangeValueScope {
|
||||
+ public:
|
||||
+ inline ChangeValueScope(Isolate* isolate, Arguments* args, int index,
|
||||
+ Object value);
|
||||
+ ~ChangeValueScope() { *location_ = old_value_->ptr(); }
|
||||
+
|
||||
+ private:
|
||||
+ Address* location_;
|
||||
+ Handle<Object> old_value_;
|
||||
+ };
|
||||
+
|
||||
Arguments(int length, Address* arguments)
|
||||
: length_(length), arguments_(arguments) {
|
||||
DCHECK_GE(length_, 0);
|
||||
@@ -51,10 +63,6 @@ class Arguments {
|
||||
|
||||
inline double number_at(int index) const;
|
||||
|
||||
- inline void set_at(int index, Object value) {
|
||||
- *address_of_arg_at(index) = value.ptr();
|
||||
- }
|
||||
-
|
||||
inline FullObjectSlot slot_at(int index) const {
|
||||
return FullObjectSlot(address_of_arg_at(index));
|
||||
}
|
||||
diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc
|
||||
index ecdab593b20be7e39251d2a7b1f499b4c6bf84c3..bef5f88dab25754c259eea5d4c7cea9a98988257 100644
|
||||
--- a/src/runtime/runtime-classes.cc
|
||||
+++ b/src/runtime/runtime-classes.cc
|
||||
@@ -619,7 +619,12 @@ MaybeHandle<Object> DefineClass(Isolate* isolate,
|
||||
|
||||
Handle<JSObject> prototype = CreateClassPrototype(isolate);
|
||||
DCHECK_EQ(*constructor, args[ClassBoilerplate::kConstructorArgumentIndex]);
|
||||
- args.set_at(ClassBoilerplate::kPrototypeArgumentIndex, *prototype);
|
||||
+ // Temporarily change ClassBoilerplate::kPrototypeArgumentIndex for the
|
||||
+ // subsequent calls, but use a scope to make sure to change it back before
|
||||
+ // returning, to not corrupt the caller's argument frame (in particular, for
|
||||
+ // the interpreter, to not clobber the register frame).
|
||||
+ RuntimeArguments::ChangeValueScope set_prototype_value_scope(
|
||||
+ isolate, &args, ClassBoilerplate::kPrototypeArgumentIndex, *prototype);
|
||||
|
||||
if (!InitClassConstructor(isolate, class_boilerplate, constructor_parent,
|
||||
constructor, args) ||
|
||||
@@ -1,2 +1,3 @@
|
||||
add_thread_local_to_x_error_trap_cc.patch
|
||||
merge_to_94_add_direction_indicator_to_transformableframes.patch
|
||||
merge_to_m96_sdp_reject_large_number_of_channels.patch
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Philipp Hancke <phancke@nvidia.com>
|
||||
Date: Thu, 25 Nov 2021 08:57:54 +0100
|
||||
Subject: sdp: reject large number of channels
|
||||
|
||||
the maximum used in practice is multiopus with
|
||||
6 or 8 channels. 24 is the maximum number of channels
|
||||
supported in the audio decoder.
|
||||
|
||||
BUG=chromium:1265806
|
||||
(cherry picked from commit d58ac5adf887a2bc96d75b1c0fb6fef17889ac80)
|
||||
|
||||
No-Try: True
|
||||
Change-Id: Iba8e3185a1f235b846fed9c154e66fb3983664ed
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/238980
|
||||
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
|
||||
Commit-Queue: Philipp Hancke <phancke@nvidia.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#35440}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/239740
|
||||
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
|
||||
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#3}
|
||||
Cr-Branched-From: 40abb7d8ff6ebdb8095d372c18949940c5fcecb5-refs/heads/main@{#35164}
|
||||
|
||||
diff --git a/pc/webrtc_sdp.cc b/pc/webrtc_sdp.cc
|
||||
index 379b2f30c2e2dfb8903da958b27af455b5431386..a5e099a70d6a2e93e4da46ebdb42490c2061fab0 100644
|
||||
--- a/pc/webrtc_sdp.cc
|
||||
+++ b/pc/webrtc_sdp.cc
|
||||
@@ -256,6 +256,9 @@ static const char kDefaultSctpmapProtocol[] = "webrtc-datachannel";
|
||||
// types.
|
||||
const int kWildcardPayloadType = -1;
|
||||
|
||||
+// Maximum number of channels allowed.
|
||||
+static const size_t kMaxNumberOfChannels = 24;
|
||||
+
|
||||
struct SsrcInfo {
|
||||
uint32_t ssrc_id;
|
||||
std::string cname;
|
||||
@@ -3626,6 +3629,10 @@ bool ParseRtpmapAttribute(const std::string& line,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+ if (channels > kMaxNumberOfChannels) {
|
||||
+ return ParseFailed(line, "At most 24 channels are supported.", error);
|
||||
+ }
|
||||
+
|
||||
AudioContentDescription* audio_desc = media_desc->as_audio();
|
||||
UpdateCodec(payload_type, encoding_name, clock_rate, 0, channels,
|
||||
audio_desc);
|
||||
diff --git a/pc/webrtc_sdp_unittest.cc b/pc/webrtc_sdp_unittest.cc
|
||||
index 266fd3dfd66155dd6f545bd542dd88f80c838cb8..4c8abac0be50253fcc7f84703a2d07ed3ba75a38 100644
|
||||
--- a/pc/webrtc_sdp_unittest.cc
|
||||
+++ b/pc/webrtc_sdp_unittest.cc
|
||||
@@ -4663,3 +4663,15 @@ TEST_F(WebRtcSdpTest, IllegalMidCharacterValue) {
|
||||
Replace("a=mid:", "a=mid:[]", &sdp);
|
||||
ExpectParseFailure(std::string(sdp), "a=mid:[]");
|
||||
}
|
||||
+
|
||||
+TEST_F(WebRtcSdpTest, MaxChannels) {
|
||||
+ std::string sdp =
|
||||
+ "v=0\r\n"
|
||||
+ "o=- 11 22 IN IP4 127.0.0.1\r\n"
|
||||
+ "s=-\r\n"
|
||||
+ "t=0 0\r\n"
|
||||
+ "m=audio 49232 RTP/AVP 108\r\n"
|
||||
+ "a=rtpmap:108 ISAC/16000/512\r\n";
|
||||
+
|
||||
+ ExpectParseFailure(sdp, "a=rtpmap:108 ISAC/16000/512");
|
||||
+}
|
||||
@@ -72,11 +72,7 @@ async function circleCIcall (targetBranch, job, options) {
|
||||
console.log(`Triggering CircleCI to run build job: ${job} on branch: ${targetBranch} with release flag.`);
|
||||
const buildRequest = {
|
||||
branch: targetBranch,
|
||||
parameters: {
|
||||
'run-lint': false,
|
||||
'run-build-linux': false,
|
||||
'run-build-mac': false
|
||||
}
|
||||
parameters: {}
|
||||
};
|
||||
if (options.ghRelease) {
|
||||
buildRequest.parameters['upload-to-s3'] = '0';
|
||||
@@ -121,8 +117,9 @@ async function getCircleCIWorkflowId (pipelineId) {
|
||||
switch (pipelineInfo.state) {
|
||||
case 'created': {
|
||||
const workflows = await circleCIRequest(`${pipelineInfoUrl}/workflow`, 'GET');
|
||||
if (workflows.items.length === 1) {
|
||||
workflowId = workflows.items[0].id;
|
||||
// The logic below expects two workflow.items: publish [0] & setup [1]
|
||||
if (workflows.items.length === 2) {
|
||||
workflowId = workflows.items.find(item => item.name.includes('publish')).id;
|
||||
break;
|
||||
}
|
||||
console.log('Unxpected number of workflows, response was:', pipelineInfo);
|
||||
|
||||
@@ -847,10 +847,10 @@ void BaseWindow::SetVisibleOnAllWorkspaces(bool visible,
|
||||
gin_helper::Dictionary options;
|
||||
bool visibleOnFullScreen = false;
|
||||
bool skipTransformProcessType = false;
|
||||
args->GetNext(&options) &&
|
||||
options.Get("visibleOnFullScreen", &visibleOnFullScreen);
|
||||
args->GetNext(&options) &&
|
||||
options.Get("skipTransformProcessType", &skipTransformProcessType);
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("visibleOnFullScreen", &visibleOnFullScreen);
|
||||
options.Get("skipTransformProcessType", &skipTransformProcessType);
|
||||
}
|
||||
return window_->SetVisibleOnAllWorkspaces(visible, visibleOnFullScreen,
|
||||
skipTransformProcessType);
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ void WebFrameMain::PostMessage(v8::Isolate* isolate,
|
||||
}
|
||||
|
||||
std::vector<gin::Handle<MessagePort>> wrapped_ports;
|
||||
if (transfer) {
|
||||
if (transfer && !transfer.value()->IsUndefined()) {
|
||||
if (!gin::ConvertFromV8(isolate, *transfer, &wrapped_ports)) {
|
||||
isolate->ThrowException(v8::Exception::Error(
|
||||
gin::StringToV8(isolate, "Invalid value for transfer")));
|
||||
|
||||
@@ -65,8 +65,8 @@ bool GetProtocolLaunchPath(gin::Arguments* args, std::wstring* exe) {
|
||||
// Read in optional args arg
|
||||
std::vector<std::wstring> launch_args;
|
||||
if (args->GetNext(&launch_args) && !launch_args.empty())
|
||||
*exe = base::StringPrintf(L"\"%ls\" %ls \"%%1\"", exe->c_str(),
|
||||
base::JoinString(launch_args, L" ").c_str());
|
||||
*exe = base::StringPrintf(L"\"%ls\" \"%ls\" \"%%1\"", exe->c_str(),
|
||||
base::JoinString(launch_args, L"\" \"").c_str());
|
||||
else
|
||||
*exe = base::StringPrintf(L"\"%ls\" \"%%1\"", exe->c_str());
|
||||
return true;
|
||||
|
||||
@@ -463,7 +463,8 @@ void ElectronBrowserMainParts::WillRunMainMessageLoop(
|
||||
std::unique_ptr<base::RunLoop>& run_loop) {
|
||||
js_env_->OnMessageLoopCreated();
|
||||
exit_code_ = content::RESULT_CODE_NORMAL_EXIT;
|
||||
Browser::Get()->SetMainMessageLoopQuitClosure(run_loop->QuitClosure());
|
||||
Browser::Get()->SetMainMessageLoopQuitClosure(
|
||||
run_loop->QuitWhenIdleClosure());
|
||||
}
|
||||
|
||||
void ElectronBrowserMainParts::PostCreateMainMessageLoop() {
|
||||
|
||||
@@ -322,15 +322,14 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
|
||||
// Set Window style so that we get a minimize and maximize animation when
|
||||
// frameless.
|
||||
DWORD frame_style = WS_CAPTION | WS_OVERLAPPED;
|
||||
if (resizable_)
|
||||
if (resizable_ && thick_frame_)
|
||||
frame_style |= WS_THICKFRAME;
|
||||
if (minimizable_)
|
||||
frame_style |= WS_MINIMIZEBOX;
|
||||
if (maximizable_)
|
||||
frame_style |= WS_MAXIMIZEBOX;
|
||||
// We should not show a frame for transparent window.
|
||||
if (!thick_frame_)
|
||||
frame_style &= ~(WS_THICKFRAME | WS_CAPTION);
|
||||
if (!thick_frame_ || !has_frame())
|
||||
frame_style &= ~WS_CAPTION;
|
||||
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
|
||||
}
|
||||
|
||||
@@ -589,14 +588,16 @@ void NativeWindowViews::Maximize() {
|
||||
#endif
|
||||
|
||||
void NativeWindowViews::Unmaximize() {
|
||||
if (IsMaximized()) {
|
||||
#if defined(OS_WIN)
|
||||
if (transparent()) {
|
||||
SetBounds(restore_bounds_, false);
|
||||
return;
|
||||
}
|
||||
if (transparent()) {
|
||||
SetBounds(restore_bounds_, false);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
widget()->Restore();
|
||||
widget()->Restore();
|
||||
}
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsMaximized() {
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 14,2,2,0
|
||||
PRODUCTVERSION 14,2,2,0
|
||||
FILEVERSION 14,2,7,0
|
||||
PRODUCTVERSION 14,2,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "14.2.2"
|
||||
VALUE "FileVersion", "14.2.7"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "14.2.2"
|
||||
VALUE "ProductVersion", "14.2.7"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -412,9 +412,8 @@ void FileChooserDialog::OnUpdatePreview(GtkFileChooser* chooser) {
|
||||
} // namespace
|
||||
|
||||
void ShowFileDialog(const FileChooserDialog& dialog) {
|
||||
if (*supports_gtk_file_chooser_native) {
|
||||
dl_gtk_native_dialog_show(static_cast<void*>(dialog.dialog()));
|
||||
} else {
|
||||
// gtk_native_dialog_run() will call gtk_native_dialog_show() for us.
|
||||
if (!*supports_gtk_file_chooser_native) {
|
||||
gtk_widget_show_all(GTK_WIDGET(dialog.dialog()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,9 @@ DialogResult ShowTaskDialogWstr(NativeWindow* parent,
|
||||
|
||||
// TaskDialogIndirect doesn't allow empty name, if we set empty title it
|
||||
// will show "electron.exe" in title.
|
||||
std::wstring app_name;
|
||||
if (title.empty()) {
|
||||
std::wstring app_name = base::UTF8ToWide(Browser::Get()->GetName());
|
||||
app_name = base::UTF8ToWide(Browser::Get()->GetName());
|
||||
config.pszWindowTitle = app_name.c_str();
|
||||
} else {
|
||||
config.pszWindowTitle = title.c_str();
|
||||
|
||||
@@ -99,4 +99,21 @@ bool ElectronDesktopWindowTreeHostWin::GetClientAreaInsets(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ElectronDesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
|
||||
// Call the default implementation of this method to get the event to its
|
||||
// proper handler.
|
||||
bool handled = views::DesktopWindowTreeHostWin::HandleMouseEvent(event);
|
||||
|
||||
// On WCO-enabled windows, we need to mark non-client mouse moved events as
|
||||
// handled so they don't incorrectly propogate back to the OS.
|
||||
if (native_window_view_->IsWindowControlsOverlayEnabled() &&
|
||||
event->type() == ui::ET_MOUSE_MOVED &&
|
||||
(event->flags() & ui::EF_IS_NON_CLIENT) != 0) {
|
||||
event->SetHandled();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -30,6 +30,7 @@ class ElectronDesktopWindowTreeHostWin
|
||||
bool GetDwmFrameInsetsInPixels(gfx::Insets* insets) const override;
|
||||
bool GetClientAreaInsets(gfx::Insets* insets,
|
||||
HMONITOR monitor) const override;
|
||||
bool HandleMouseEvent(ui::MouseEvent* event) override;
|
||||
|
||||
private:
|
||||
NativeWindowViews* native_window_view_; // weak ref
|
||||
|
||||
@@ -21,7 +21,9 @@ WindowStateWatcher::WindowStateWatcher(NativeWindowViews* window)
|
||||
x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")),
|
||||
net_wm_state_maximized_horz_atom_(
|
||||
x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")),
|
||||
net_wm_state_fullscreen_atom_(x11::GetAtom("_NET_WM_STATE_FULLSCREEN")) {
|
||||
net_wm_state_fullscreen_atom_(x11::GetAtom("_NET_WM_STATE_FULLSCREEN")),
|
||||
was_minimized_(window_->IsMinimized()),
|
||||
was_maximized_(window_->IsMaximized()) {
|
||||
ui::X11EventSource::GetInstance()->connection()->AddEventObserver(this);
|
||||
}
|
||||
|
||||
@@ -31,9 +33,6 @@ WindowStateWatcher::~WindowStateWatcher() {
|
||||
|
||||
void WindowStateWatcher::OnEvent(const x11::Event& x11_event) {
|
||||
if (IsWindowStateEvent(x11_event)) {
|
||||
const bool was_minimized_ = window_->IsMinimized();
|
||||
const bool was_maximized_ = window_->IsMaximized();
|
||||
|
||||
std::vector<x11::Atom> wm_states;
|
||||
if (GetArrayProperty(
|
||||
static_cast<x11::Window>(window_->GetAcceleratedWidget()),
|
||||
@@ -67,6 +66,9 @@ void WindowStateWatcher::OnEvent(const x11::Event& x11_event) {
|
||||
else
|
||||
window_->NotifyWindowLeaveFullScreen();
|
||||
}
|
||||
|
||||
was_minimized_ = is_minimized;
|
||||
was_maximized_ = is_maximized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ class WindowStateWatcher : public x11::EventObserver {
|
||||
const x11::Atom net_wm_state_maximized_horz_atom_;
|
||||
const x11::Atom net_wm_state_fullscreen_atom_;
|
||||
|
||||
bool was_minimized_ = false;
|
||||
bool was_maximized_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WindowStateWatcher);
|
||||
};
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ void WebViewGuestDelegate::OnZoomLevelChanged(
|
||||
api_web_contents_->GetZoomController()->SetZoomLevel(level);
|
||||
}
|
||||
// Change the default zoom factor to match the embedders' new zoom level.
|
||||
double zoom_factor = blink::PageZoomFactorToZoomLevel(level);
|
||||
double zoom_factor = blink::PageZoomLevelToZoomFactor(level);
|
||||
api_web_contents_->GetZoomController()->SetDefaultZoomFactor(zoom_factor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer>,
|
||||
}
|
||||
|
||||
std::vector<v8::Local<v8::Object>> transferables;
|
||||
if (transfer) {
|
||||
if (transfer && !transfer.value()->IsUndefined()) {
|
||||
if (!gin::ConvertFromV8(isolate, *transfer, &transferables)) {
|
||||
thrower.ThrowTypeError("Invalid value for transfer");
|
||||
return;
|
||||
|
||||
@@ -495,6 +495,14 @@ class WebFrameRenderer : public gin::Wrappable<WebFrameRenderer>,
|
||||
return gin::ConvertToV8(isolate, prefs.context_isolation);
|
||||
} else if (pref_name == options::kGuestInstanceID) {
|
||||
// NOTE: guestInstanceId is internal-only.
|
||||
// FIXME(zcbenz): For child windows opened with window.open('') from
|
||||
// webview, the WebPreferences is inherited from webview and the value
|
||||
// of |guest_instance_id| is wrong.
|
||||
// Please check ElectronRenderFrameObserver::DidInstallConditionalFeatures
|
||||
// for the background.
|
||||
auto* web_frame = render_frame->GetWebFrame();
|
||||
if (web_frame->Opener())
|
||||
return gin::ConvertToV8(isolate, 0);
|
||||
return gin::ConvertToV8(isolate, prefs.guest_instance_id);
|
||||
} else if (pref_name == options::kHiddenPage) {
|
||||
// NOTE: hiddenPage is internal-only.
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "third_party/blink/public/web/web_element.h"
|
||||
#include "third_party/blink/public/web/web_local_frame.h"
|
||||
#include "third_party/blink/public/web/web_script_source.h"
|
||||
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" // nogncheck
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
|
||||
namespace electron {
|
||||
@@ -58,12 +59,57 @@ ElectronRenderFrameObserver::ElectronRenderFrameObserver(
|
||||
}
|
||||
|
||||
void ElectronRenderFrameObserver::DidClearWindowObject() {
|
||||
// Do a delayed Node.js initialization for child window.
|
||||
// Check DidInstallConditionalFeatures below for the background.
|
||||
auto* web_frame =
|
||||
static_cast<blink::WebLocalFrameImpl*>(render_frame_->GetWebFrame());
|
||||
if (has_delayed_node_initialization_ && web_frame->Opener() &&
|
||||
web_frame->HasCommittedFirstRealLoad()) {
|
||||
v8::Isolate* isolate = blink::MainThreadIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::MicrotasksScope microtasks_scope(
|
||||
isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
|
||||
v8::Handle<v8::Context> context = web_frame->MainWorldScriptContext();
|
||||
v8::Context::Scope context_scope(context);
|
||||
// DidClearWindowObject only emits for the main world.
|
||||
DidInstallConditionalFeatures(context, MAIN_WORLD_ID);
|
||||
}
|
||||
|
||||
renderer_client_->DidClearWindowObject(render_frame_);
|
||||
}
|
||||
|
||||
void ElectronRenderFrameObserver::DidInstallConditionalFeatures(
|
||||
v8::Handle<v8::Context> context,
|
||||
int world_id) {
|
||||
// When a child window is created with window.open, its WebPreferences will
|
||||
// be copied from its parent, and Chromium will intialize JS context in it
|
||||
// immediately.
|
||||
// Normally the WebPreferences is overriden in browser before navigation,
|
||||
// but this behavior bypasses the browser side navigation and the child
|
||||
// window will get wrong WebPreferences in the initialization.
|
||||
// This will end up initializing Node.js in the child window with wrong
|
||||
// WebPreferences, leads to problem that child window having node integration
|
||||
// while "nodeIntegration=no" is passed.
|
||||
// We work around this issue by delaying the child window's initialization of
|
||||
// Node.js if this is the initial empty document, and only do it when the
|
||||
// acutal page has started to load.
|
||||
auto* web_frame =
|
||||
static_cast<blink::WebLocalFrameImpl*>(render_frame_->GetWebFrame());
|
||||
if (web_frame->Opener() && !web_frame->HasCommittedFirstRealLoad()) {
|
||||
// FIXME(zcbenz): Chromium does not do any browser side navigation for
|
||||
// window.open('about:blank'), so there is no way to override WebPreferences
|
||||
// of it. We should not delay Node.js initialization as there will be no
|
||||
// further loadings.
|
||||
// Please check http://crbug.com/1215096 for updates which may help remove
|
||||
// this hack.
|
||||
GURL url = web_frame->GetDocument().Url();
|
||||
if (!url.IsAboutBlank()) {
|
||||
has_delayed_node_initialization_ = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
has_delayed_node_initialization_ = false;
|
||||
|
||||
auto* isolate = context->GetIsolate();
|
||||
v8::MicrotasksScope microtasks_scope(
|
||||
isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
|
||||
|
||||
@@ -42,6 +42,7 @@ class ElectronRenderFrameObserver : public content::RenderFrameObserver {
|
||||
void OnTakeHeapSnapshot(IPC::PlatformFileForTransit file_handle,
|
||||
const std::string& channel);
|
||||
|
||||
bool has_delayed_node_initialization_ = false;
|
||||
content::RenderFrame* render_frame_;
|
||||
RendererClientBase* renderer_client_;
|
||||
|
||||
|
||||
@@ -153,6 +153,7 @@ void ElectronRendererClient::WillReleaseScriptContext(
|
||||
// We also do this if we have disable electron site instance overrides to
|
||||
// avoid memory leaks
|
||||
auto prefs = render_frame->GetBlinkPreferences();
|
||||
gin_helper::MicrotasksScope microtasks_scope(env->isolate());
|
||||
node::FreeEnvironment(env);
|
||||
if (env == node_bindings_->uv_env())
|
||||
node::FreeIsolateData(node_bindings_->isolate_data());
|
||||
|
||||
@@ -36,6 +36,8 @@ WebWorkerObserver::WebWorkerObserver()
|
||||
|
||||
WebWorkerObserver::~WebWorkerObserver() {
|
||||
lazy_tls.Pointer()->Set(nullptr);
|
||||
gin_helper::MicrotasksScope microtasks_scope(
|
||||
node_bindings_->uv_env()->isolate());
|
||||
node::FreeEnvironment(node_bindings_->uv_env());
|
||||
node::FreeIsolateData(node_bindings_->isolate_data());
|
||||
}
|
||||
|
||||
@@ -3417,6 +3417,29 @@ describe('BrowserWindow module', () => {
|
||||
w.unmaximize();
|
||||
expectBoundsEqual(w.getPosition(), initialPosition);
|
||||
});
|
||||
|
||||
// TODO(dsanders11): Enable once minimize event works on Linux again.
|
||||
// See https://github.com/electron/electron/issues/28699
|
||||
ifit(process.platform !== 'linux')('should not restore a minimized window', async () => {
|
||||
const w = new BrowserWindow();
|
||||
const minimize = emittedOnce(w, 'minimize');
|
||||
w.minimize();
|
||||
await minimize;
|
||||
w.unmaximize();
|
||||
await delay(1000);
|
||||
expect(w.isMinimized()).to.be.true();
|
||||
});
|
||||
|
||||
it('should not change the size or position of a normal window', async () => {
|
||||
const w = new BrowserWindow();
|
||||
|
||||
const initialSize = w.getSize();
|
||||
const initialPosition = w.getPosition();
|
||||
w.unmaximize();
|
||||
await delay(1000);
|
||||
expectBoundsEqual(w.getSize(), initialSize);
|
||||
expectBoundsEqual(w.getPosition(), initialPosition);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setFullScreen(false)', () => {
|
||||
|
||||
@@ -216,6 +216,18 @@ describe('ipc module', () => {
|
||||
expect(port).to.be.an.instanceOf(EventEmitter);
|
||||
});
|
||||
|
||||
it('can sent a message without a transfer', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, contextIsolation: false } });
|
||||
w.loadURL('about:blank');
|
||||
const p = emittedOnce(ipcMain, 'port');
|
||||
await w.webContents.executeJavaScript(`(${function () {
|
||||
require('electron').ipcRenderer.postMessage('port', 'hi');
|
||||
}})()`);
|
||||
const [ev, msg] = await p;
|
||||
expect(msg).to.equal('hi');
|
||||
expect(ev.ports).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it('can communicate between main and renderer', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, contextIsolation: false } });
|
||||
w.loadURL('about:blank');
|
||||
|
||||
@@ -811,6 +811,17 @@ describe('chromium features', () => {
|
||||
expect(typeofProcessGlobal).to.equal('undefined');
|
||||
});
|
||||
|
||||
it('can disable node integration when it is enabled on the parent window with nativeWindowOpen: true', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, nativeWindowOpen: true } });
|
||||
w.loadURL('about:blank');
|
||||
w.webContents.executeJavaScript(`
|
||||
{ b = window.open('about:blank', '', 'nodeIntegration=no,show=no'); null }
|
||||
`);
|
||||
const [, contents] = await emittedOnce(app, 'web-contents-created');
|
||||
const typeofProcessGlobal = await contents.executeJavaScript('typeof process');
|
||||
expect(typeofProcessGlobal).to.equal('undefined');
|
||||
});
|
||||
|
||||
it('disables JavaScript when it is disabled on the parent window', async () => {
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
|
||||
w.webContents.loadURL('about:blank');
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
// `setImmediate` schedules a function to be run on the next UV tick, which
|
||||
// ensures that `window.open` is run from `UvRunOnce()`.
|
||||
setImmediate(async () => {
|
||||
if (!location.hash) {
|
||||
if (location.hash) {
|
||||
window.opener.postMessage('foo', '*');
|
||||
} else {
|
||||
// `setImmediate` schedules a function to be run on the next UV tick, which
|
||||
// ensures that `window.open` is run from `UvRunOnce()`.
|
||||
setImmediate(async () => {
|
||||
const p = new Promise(resolve => {
|
||||
window.addEventListener('message', resolve, { once: true });
|
||||
});
|
||||
@@ -12,10 +14,8 @@ setImmediate(async () => {
|
||||
const e = await p;
|
||||
|
||||
window.close();
|
||||
} else {
|
||||
window.opener.postMessage('foo', '*');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -227,7 +227,8 @@ describe('<webview> tag', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('loads devtools extensions registered on the parent window', async () => {
|
||||
// This test is flaky on WOA, so skip it there.
|
||||
ifit(process.platform !== 'win32' || process.arch !== 'arm64')('loads devtools extensions registered on the parent window', async () => {
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
|
||||
@@ -8,7 +8,7 @@ const ChildProcess = require('child_process');
|
||||
const { ipcRenderer } = require('electron');
|
||||
const { emittedOnce, waitForEvent } = require('./events-helpers');
|
||||
const { resolveGetters } = require('./expect-helpers');
|
||||
const { ifdescribe, delay } = require('./spec-helpers');
|
||||
const { ifit, ifdescribe, delay } = require('./spec-helpers');
|
||||
const features = process._linkedBinding('electron_common_features');
|
||||
|
||||
/* Most of the APIs here don't use standard callbacks */
|
||||
@@ -81,7 +81,8 @@ describe('chromium feature', () => {
|
||||
expect(event.data).to.equal(`size: ${width} ${height}`);
|
||||
});
|
||||
|
||||
it('disables node integration when it is disabled on the parent window', async () => {
|
||||
// FIXME(zcbenz): This test is making the spec runner hang on exit on Windows.
|
||||
ifit(process.platform !== 'win32')('disables node integration when it is disabled on the parent window', async () => {
|
||||
const windowUrl = require('url').format({
|
||||
pathname: `${fixtures}/pages/window-opener-no-node-integration.html`,
|
||||
protocol: 'file',
|
||||
@@ -154,16 +155,6 @@ describe('chromium feature', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('window.postMessage', () => {
|
||||
it('throws an exception when the targetOrigin cannot be converted to a string', () => {
|
||||
const b = window.open('');
|
||||
expect(() => {
|
||||
b.postMessage('test', { toString: null });
|
||||
}).to.throw('Cannot convert object to primitive value');
|
||||
b.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('window.opener.postMessage', () => {
|
||||
it('sets source and origin correctly', async () => {
|
||||
const message = waitForEvent(window, 'message');
|
||||
|
||||
10
yarn.lock
10
yarn.lock
@@ -1693,16 +1693,16 @@ color-name@~1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
colors@1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
||||
colors@^1.1.2:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
|
||||
integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
|
||||
|
||||
colors@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
|
||||
Reference in New Issue
Block a user