Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: webview zoom level persistence on navigation #41269

Merged
merged 1 commit into from Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 9 additions & 5 deletions shell/browser/web_contents_zoom_controller.cc
Expand Up @@ -74,6 +74,7 @@ bool WebContentsZoomController::SetZoomLevel(double level) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
content::NavigationEntry* entry =
web_contents()->GetController().GetLastCommittedEntry();

// Cannot zoom in disabled mode. Also, don't allow changing zoom level on
// a crashed tab, an error page or an interstitial page.
if (zoom_mode_ == ZOOM_MODE_DISABLED ||
Expand All @@ -90,7 +91,7 @@ bool WebContentsZoomController::SetZoomLevel(double level) {
zoom_level_ = level;

ZoomChangedEventData zoom_change_data(web_contents(), old_zoom_level,
zoom_level_, false /* temporary */,
zoom_level_, true /* temporary */,
zoom_mode_);
for (auto& observer : observers_)
observer.OnZoomChanged(zoom_change_data);
Expand Down Expand Up @@ -154,7 +155,7 @@ void WebContentsZoomController::SetTemporaryZoomLevel(double level) {
// Notify observers of zoom level changes.
ZoomChangedEventData zoom_change_data(web_contents(), zoom_level_, level,
true /* temporary */, zoom_mode_);
for (WebContentsZoomObserver& observer : observers_)
for (auto& observer : observers_)
observer.OnZoomChanged(zoom_change_data);
}

Expand Down Expand Up @@ -268,8 +269,10 @@ void WebContentsZoomController::ResetZoomModeOnNavigationIfNeeded(
double old_zoom_level = zoom_map->GetZoomLevel(web_contents());
double new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme(
url.scheme(), net::GetHostOrSpecFromURL(url));

event_data_ = std::make_unique<ZoomChangedEventData>(
web_contents(), old_zoom_level, new_zoom_level, false, ZOOM_MODE_DEFAULT);

// The call to ClearTemporaryZoomLevel() doesn't generate any events from
// HostZoomMap, but the call to UpdateState() at the end of
// DidFinishNavigation will notify our observers.
Expand All @@ -295,11 +298,12 @@ void WebContentsZoomController::DidFinishNavigation(
if (!navigation_handle->IsSameDocument()) {
ResetZoomModeOnNavigationIfNeeded(navigation_handle->GetURL());
SetZoomFactorOnNavigationIfNeeded(navigation_handle->GetURL());

// If the main frame's content has changed, the new page may have a
// different zoom level from the old one.
UpdateState(std::string());
}

// If the main frame's content has changed, the new page may have a different
// zoom level from the old one.
UpdateState(std::string());
DCHECK(!event_data_);
}

Expand Down
31 changes: 31 additions & 0 deletions spec/fixtures/pages/webview-zoom-change-persist-host.html
@@ -0,0 +1,31 @@
<html>

<body>
<webview nodeintegration src="app://host1" id="view" partition="webview-temp" />
</body>
<script>
const { ipcRenderer, webFrame } = require('electron')
const view = document.getElementById('view')

let values = {
initialZoomLevel: 0,
switchZoomLevel: 0,
finalZoomLevel: 0,
}

view.addEventListener('dom-ready', async () => {
view.setZoomLevel(2.0)
values.initialZoomLevel = view.getZoomLevel()

await view.loadURL('app://host2')
view.setZoomLevel(3.0)
values.switchZoomLevel = view.getZoomLevel()

await view.loadURL('app://host1')
values.finalZoomLevel = view.getZoomLevel()

ipcRenderer.send('webview-zoom-persist-level', values)
})
</script>

</html>
8 changes: 7 additions & 1 deletion spec/node-spec.ts
Expand Up @@ -940,7 +940,13 @@ describe('node feature', () => {
});
};

process.once('unhandledRejection', () => done('catch block is delayed to next tick'));
let called = false;
process.once('unhandledRejection', () => {
if (called) return;

done(new Error('catch block is delayed to next tick'));
called = true;
});

setTimeout(() => {
f3().catch(() => done());
Expand Down
25 changes: 25 additions & 0 deletions spec/webview-spec.ts
Expand Up @@ -352,6 +352,31 @@ describe('<webview> tag', function () {
expect(zoomLevel).to.equal(1);
});

it('maintains the zoom level for a given host in the same session after navigation', () => {
const w = new BrowserWindow({
show: false,
webPreferences: {
webviewTag: true,
nodeIntegration: true,
contextIsolation: false
}
});

const zoomPromise = new Promise<void>((resolve) => {
ipcMain.on('webview-zoom-persist-level', (_event, values) => {
resolve(values);
});
});

w.loadFile(path.join(fixtures, 'pages', 'webview-zoom-change-persist-host.html'));

expect(zoomPromise).to.eventually.deep.equal({
initialZoomLevel: 2,
switchZoomLevel: 3,
finalZoomLevel: 2
});
});

it('maintains zoom level on navigation', async () => {
const w = new BrowserWindow({
show: false,
Expand Down