fix: webContents.capturePage()
for hidden windows on Windows/Linux (#39730)
This commit is contained in:
parent
3e70692e4b
commit
5c821d3379
2 changed files with 30 additions and 25 deletions
|
@ -469,9 +469,16 @@ base::IDMap<WebContents*>& GetAllWebContents() {
|
||||||
void OnCapturePageDone(gin_helper::Promise<gfx::Image> promise,
|
void OnCapturePageDone(gin_helper::Promise<gfx::Image> promise,
|
||||||
base::ScopedClosureRunner capture_handle,
|
base::ScopedClosureRunner capture_handle,
|
||||||
const SkBitmap& bitmap) {
|
const SkBitmap& bitmap) {
|
||||||
|
auto ui_task_runner = content::GetUIThreadTaskRunner({});
|
||||||
|
if (!ui_task_runner->RunsTasksInCurrentSequence()) {
|
||||||
|
ui_task_runner->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&OnCapturePageDone, std::move(promise),
|
||||||
|
std::move(capture_handle), bitmap));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Hack to enable transparency in captured image
|
// Hack to enable transparency in captured image
|
||||||
promise.Resolve(gfx::Image::CreateFrom1xBitmap(bitmap));
|
promise.Resolve(gfx::Image::CreateFrom1xBitmap(bitmap));
|
||||||
|
|
||||||
capture_handle.RunAndReset();
|
capture_handle.RunAndReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3462,22 +3469,16 @@ v8::Local<v8::Promise> WebContents::CapturePage(gin::Arguments* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* const view = web_contents()->GetRenderWidgetHostView();
|
auto* const view = web_contents()->GetRenderWidgetHostView();
|
||||||
if (!view) {
|
if (!view || view->GetViewBounds().size().IsEmpty()) {
|
||||||
promise.Resolve(gfx::Image());
|
promise.Resolve(gfx::Image());
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !BUILDFLAG(IS_MAC)
|
if (!view->IsSurfaceAvailableForCopy()) {
|
||||||
// If the view's renderer is suspended this may fail on Windows/Linux -
|
promise.RejectWithErrorMessage(
|
||||||
// bail if so. See CopyFromSurface in
|
"Current display surface not available for capture");
|
||||||
// content/public/browser/render_widget_host_view.h.
|
|
||||||
auto* rfh = web_contents()->GetPrimaryMainFrame();
|
|
||||||
if (rfh &&
|
|
||||||
rfh->GetVisibilityState() == blink::mojom::PageVisibilityState::kHidden) {
|
|
||||||
promise.Resolve(gfx::Image());
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
|
||||||
|
|
||||||
auto capture_handle = web_contents()->IncrementCapturerCount(
|
auto capture_handle = web_contents()->IncrementCapturerCount(
|
||||||
rect.size(), stay_hidden, stay_awake);
|
rect.size(), stay_hidden, stay_awake);
|
||||||
|
|
|
@ -2224,7 +2224,22 @@ describe('BrowserWindow module', () => {
|
||||||
expect(visible).to.equal('hidden');
|
expect(visible).to.equal('hidden');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resolves after the window is hidden', async () => {
|
it('resolves when the window is occluded', async () => {
|
||||||
|
const w1 = new BrowserWindow({ show: false });
|
||||||
|
w1.loadFile(path.join(fixtures, 'pages', 'a.html'));
|
||||||
|
await once(w1, 'ready-to-show');
|
||||||
|
w1.show();
|
||||||
|
|
||||||
|
const w2 = new BrowserWindow({ show: false });
|
||||||
|
w2.loadFile(path.join(fixtures, 'pages', 'a.html'));
|
||||||
|
await once(w2, 'ready-to-show');
|
||||||
|
w2.show();
|
||||||
|
|
||||||
|
const visibleImage = await w1.capturePage();
|
||||||
|
expect(visibleImage.isEmpty()).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resolves when the window is not visible', async () => {
|
||||||
const w = new BrowserWindow({ show: false });
|
const w = new BrowserWindow({ show: false });
|
||||||
w.loadFile(path.join(fixtures, 'pages', 'a.html'));
|
w.loadFile(path.join(fixtures, 'pages', 'a.html'));
|
||||||
await once(w, 'ready-to-show');
|
await once(w, 'ready-to-show');
|
||||||
|
@ -2233,21 +2248,10 @@ describe('BrowserWindow module', () => {
|
||||||
const visibleImage = await w.capturePage();
|
const visibleImage = await w.capturePage();
|
||||||
expect(visibleImage.isEmpty()).to.equal(false);
|
expect(visibleImage.isEmpty()).to.equal(false);
|
||||||
|
|
||||||
w.hide();
|
w.minimize();
|
||||||
|
|
||||||
const hiddenImage = await w.capturePage();
|
const hiddenImage = await w.capturePage();
|
||||||
const isEmpty = process.platform !== 'darwin';
|
expect(hiddenImage.isEmpty()).to.equal(false);
|
||||||
expect(hiddenImage.isEmpty()).to.equal(isEmpty);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('resolves after the window is hidden and capturer count is non-zero', async () => {
|
|
||||||
const w = new BrowserWindow({ show: false });
|
|
||||||
w.webContents.setBackgroundThrottling(false);
|
|
||||||
w.loadFile(path.join(fixtures, 'pages', 'a.html'));
|
|
||||||
await once(w, 'ready-to-show');
|
|
||||||
|
|
||||||
const image = await w.capturePage();
|
|
||||||
expect(image.isEmpty()).to.equal(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('preserves transparency', async () => {
|
it('preserves transparency', async () => {
|
||||||
|
|
Loading…
Reference in a new issue