feat: duplicate navigation related APIs to contents.navigationHistory (#41752)

* refactor: move navigation related api to navigationHistory

* docs: add deprecation messages to old web content methods

* fix: add deprecation warnings to webcontents

* fix: add deprecation warnings and make existing naviagation apis internal

* Update docs/api/web-contents.md

Co-authored-by: Sam Maddock <samuel.maddock@gmail.com>

* Update docs/api/web-contents.md

Co-authored-by: Sam Maddock <samuel.maddock@gmail.com>

* Update docs/api/web-contents.md

Co-authored-by: Sam Maddock <samuel.maddock@gmail.com>

* Update docs/api/web-contents.md

Co-authored-by: Sam Maddock <samuel.maddock@gmail.com>

* docs: fix links

* docs: add breaking change to 31

* docs: move breaking change to 32

* chore: re-run pipeline

---------

Co-authored-by: Sam Maddock <samuel.maddock@gmail.com>
This commit is contained in:
Alice Zhao 2024-06-05 09:34:47 -07:00 committed by GitHub
parent 5fb117a7d7
commit 406f644d26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 239 additions and 17 deletions

View file

@ -9,6 +9,24 @@ Each navigation entry corresponds to a specific page. The indexing system follow
### Instance Methods ### Instance Methods
#### `navigationHistory.canGoBack()`
Returns `boolean` - Whether the browser can go back to previous web page.
#### `navigationHistory.canGoForward()`
Returns `boolean` - Whether the browser can go forward to next web page.
#### `navigationHistory.canGoToOffset(offset)`
* `offset` Integer
Returns `boolean` - Whether the web page can go to the specified `offset` from the current entry.
#### `navigationHistory.clear()`
Clears the navigation history.
#### `navigationHistory.getActiveIndex()` #### `navigationHistory.getActiveIndex()`
Returns `Integer` - The index of the current page, from which we would go back/forward or reload. Returns `Integer` - The index of the current page, from which we would go back/forward or reload.
@ -24,6 +42,26 @@ Returns `Object`:
If index is out of bounds (greater than history length or less than 0), null will be returned. If index is out of bounds (greater than history length or less than 0), null will be returned.
#### `navigationHistory.goBack()`
Makes the browser go back a web page.
#### `navigationHistory.goForward()`
Makes the browser go forward a web page.
#### `navigationHistory.goToIndex(index)`
* `index` Integer
Navigates browser to the specified absolute web page index.
#### `navigationHistory.goToOffset(offset)`
* `offset` Integer
Navigates to the specified offset from the current entry.
#### `navigationHistory.length()` #### `navigationHistory.length()`
Returns `Integer` - History length. Returns `Integer` - History length.

View file

@ -1124,44 +1124,60 @@ Reloads the current web page.
Reloads current page and ignores cache. Reloads current page and ignores cache.
#### `contents.canGoBack()` #### `contents.canGoBack()` _Deprecated_
Returns `boolean` - Whether the browser can go back to previous web page. Returns `boolean` - Whether the browser can go back to previous web page.
#### `contents.canGoForward()` **Deprecated:** Should use the new [`contents.navigationHistory.canGoBack`](navigation-history.md#navigationhistorycangoback) API.
#### `contents.canGoForward()` _Deprecated_
Returns `boolean` - Whether the browser can go forward to next web page. Returns `boolean` - Whether the browser can go forward to next web page.
#### `contents.canGoToOffset(offset)` **Deprecated:** Should use the new [`contents.navigationHistory.canGoForward`](navigation-history.md#navigationhistorycangoforward) API.
#### `contents.canGoToOffset(offset)` _Deprecated_
* `offset` Integer * `offset` Integer
Returns `boolean` - Whether the web page can go to `offset`. Returns `boolean` - Whether the web page can go to `offset`.
#### `contents.clearHistory()` **Deprecated:** Should use the new [`contents.navigationHistory.canGoToOffset`](navigation-history.md#navigationhistorycangotooffsetoffset) API.
#### `contents.clearHistory()` _Deprecated_
Clears the navigation history. Clears the navigation history.
#### `contents.goBack()` **Deprecated:** Should use the new [`contents.navigationHistory.clear`](navigation-history.md#navigationhistoryclear) API.
#### `contents.goBack()` _Deprecated_
Makes the browser go back a web page. Makes the browser go back a web page.
#### `contents.goForward()` **Deprecated:** Should use the new [`contents.navigationHistory.goBack`](navigation-history.md#navigationhistorygoback) API.
#### `contents.goForward()` _Deprecated_
Makes the browser go forward a web page. Makes the browser go forward a web page.
#### `contents.goToIndex(index)` **Deprecated:** Should use the new [`contents.navigationHistory.goForward`](navigation-history.md#navigationhistorygoforward) API.
#### `contents.goToIndex(index)` _Deprecated_
* `index` Integer * `index` Integer
Navigates browser to the specified absolute web page index. Navigates browser to the specified absolute web page index.
#### `contents.goToOffset(offset)` **Deprecated:** Should use the new [`contents.navigationHistory.goToIndex`](navigation-history.md#navigationhistorygotoindexindex) API.
#### `contents.goToOffset(offset)` _Deprecated_
* `offset` Integer * `offset` Integer
Navigates to the specified offset from the "current entry". Navigates to the specified offset from the "current entry".
**Deprecated:** Should use the new [`contents.navigationHistory.goToOffset`](navigation-history.md#navigationhistorygotooffsetoffset) API.
#### `contents.isCrashed()` #### `contents.isCrashed()`
Returns `boolean` - Whether the renderer process has crashed. Returns `boolean` - Whether the renderer process has crashed.

View file

@ -44,6 +44,32 @@ contextBridge.exposeInMainWorld('electron', {
}) })
``` ```
### Deprecated: `clearHistory`, `canGoBack`, `goBack`, `canGoForward`, `goForward`, `canGoToOffset`, `goToOffset` on `WebContents`
The navigation-related APIs are now deprecated.
These APIs have been moved to the `navigationHistory` property of `WebContents` to provide a more structured and intuitive interface for managing navigation history.
```js
// Deprecated
win.webContents.clearHistory()
win.webContents.canGoBack()
win.webContents.goBack()
win.webContents.canGoForward()
win.webContents.goForward()
win.webContents.canGoToOffset()
win.webContents.goToOffset(index)
// Replace with
win.webContents.navigationHistory.clear()
win.webContents.navigationHistory.canGoBack()
win.webContents.navigationHistory.goBack()
win.webContents.navigationHistory.canGoForward()
win.webContents.navigationHistory.goForward()
win.webContents.navigationHistory.canGoToOffset()
win.webContents.navigationHistory.goToOffset(index)
```
## Planned Breaking API Changes (31.0) ## Planned Breaking API Changes (31.0)
### Removed: `WebSQL` support ### Removed: `WebSQL` support
@ -52,7 +78,7 @@ Chromium has removed support for WebSQL upstream, transitioning it to Android on
[Chromium's intent to remove discussion](https://groups.google.com/a/chromium.org/g/blink-dev/c/fWYb6evVA-w/m/wGI863zaAAAJ) [Chromium's intent to remove discussion](https://groups.google.com/a/chromium.org/g/blink-dev/c/fWYb6evVA-w/m/wGI863zaAAAJ)
for more information. for more information.
### Behavior Changed: `nativeImage.toDataURL` will preseve PNG colorspace ### Behavior Changed: `nativeImage.toDataURL` will preserve PNG colorspace
PNG decoder implementation has been changed to preserve colorspace data, the PNG decoder implementation has been changed to preserve colorspace data, the
encoded data returned from this function now matches it. encoded data returned from this function now matches it.

View file

@ -510,6 +510,54 @@ const environment = process._linkedBinding('electron_common_environment');
const loggingEnabled = () => { const loggingEnabled = () => {
return environment.hasVar('ELECTRON_ENABLE_LOGGING') || commandLine.hasSwitch('enable-logging'); return environment.hasVar('ELECTRON_ENABLE_LOGGING') || commandLine.hasSwitch('enable-logging');
}; };
// Deprecation warnings for navigation related APIs.
const canGoBackDeprecated = deprecate.warnOnce('webContents.canGoBack', 'webContents.navigationHistory.canGoBack');
WebContents.prototype.canGoBack = function () {
canGoBackDeprecated();
return this._canGoBack();
};
const canGoForwardDeprecated = deprecate.warnOnce('webContents.canGoForward', 'webContents.navigationHistory.canGoForward');
WebContents.prototype.canGoForward = function () {
canGoForwardDeprecated();
return this._canGoForward();
};
const canGoToOffsetDeprecated = deprecate.warnOnce('webContents.canGoToOffset', 'webContents.navigationHistory.canGoToOffset');
WebContents.prototype.canGoToOffset = function () {
canGoToOffsetDeprecated();
return this._canGoToOffset();
};
const clearHistoryDeprecated = deprecate.warnOnce('webContents.clearHistory', 'webContents.navigationHistory.clear');
WebContents.prototype.clearHistory = function () {
clearHistoryDeprecated();
return this._clearHistory();
};
const goBackDeprecated = deprecate.warnOnce('webContents.goBack', 'webContents.navigationHistory.goBack');
WebContents.prototype.goBack = function () {
goBackDeprecated();
return this._goBack();
};
const goForwardDeprecated = deprecate.warnOnce('webContents.goForward', 'webContents.navigationHistory.goForward');
WebContents.prototype.goForward = function () {
goForwardDeprecated();
return this._goForward();
};
const goToIndexDeprecated = deprecate.warnOnce('webContents.goToIndex', 'webContents.navigationHistory.goToIndex');
WebContents.prototype.goToIndex = function (index: number) {
goToIndexDeprecated();
return this._goToIndex(index);
};
const goToOffsetDeprecated = deprecate.warnOnce('webContents.goToOffset', 'webContents.navigationHistory.goToOffset');
WebContents.prototype.goToOffset = function (index: number) {
goToOffsetDeprecated();
return this._goToOffset(index);
};
// Add JavaScript wrappers for WebContents class. // Add JavaScript wrappers for WebContents class.
WebContents.prototype._init = function () { WebContents.prototype._init = function () {
@ -537,6 +585,14 @@ WebContents.prototype._init = function () {
// maintaining a list of navigation entries for backward and forward navigation. // maintaining a list of navigation entries for backward and forward navigation.
Object.defineProperty(this, 'navigationHistory', { Object.defineProperty(this, 'navigationHistory', {
value: { value: {
canGoBack: this._canGoBack.bind(this),
canGoForward: this._canGoForward.bind(this),
canGoToOffset: this._canGoToOffset.bind(this),
clear: this._clearHistory.bind(this),
goBack: this._goBack.bind(this),
goForward: this._goForward.bind(this),
goToIndex: this._goToIndex.bind(this),
goToOffset: this._goToOffset.bind(this),
getActiveIndex: this._getActiveIndex.bind(this), getActiveIndex: this._getActiveIndex.bind(this),
length: this._historyLength.bind(this), length: this._historyLength.bind(this),
getEntryAtIndex: this._getNavigationEntryAtIndex.bind(this) getEntryAtIndex: this._getNavigationEntryAtIndex.bind(this)

View file

@ -4276,19 +4276,19 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
.SetMethod("isLoadingMainFrame", &WebContents::IsLoadingMainFrame) .SetMethod("isLoadingMainFrame", &WebContents::IsLoadingMainFrame)
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse) .SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
.SetMethod("stop", &WebContents::Stop) .SetMethod("stop", &WebContents::Stop)
.SetMethod("canGoBack", &WebContents::CanGoBack) .SetMethod("_canGoBack", &WebContents::CanGoBack)
.SetMethod("goBack", &WebContents::GoBack) .SetMethod("_goBack", &WebContents::GoBack)
.SetMethod("canGoForward", &WebContents::CanGoForward) .SetMethod("_canGoForward", &WebContents::CanGoForward)
.SetMethod("goForward", &WebContents::GoForward) .SetMethod("_goForward", &WebContents::GoForward)
.SetMethod("canGoToOffset", &WebContents::CanGoToOffset) .SetMethod("_canGoToOffset", &WebContents::CanGoToOffset)
.SetMethod("goToOffset", &WebContents::GoToOffset) .SetMethod("_goToOffset", &WebContents::GoToOffset)
.SetMethod("canGoToIndex", &WebContents::CanGoToIndex) .SetMethod("canGoToIndex", &WebContents::CanGoToIndex)
.SetMethod("goToIndex", &WebContents::GoToIndex) .SetMethod("_goToIndex", &WebContents::GoToIndex)
.SetMethod("_getActiveIndex", &WebContents::GetActiveIndex) .SetMethod("_getActiveIndex", &WebContents::GetActiveIndex)
.SetMethod("_getNavigationEntryAtIndex", .SetMethod("_getNavigationEntryAtIndex",
&WebContents::GetNavigationEntryAtIndex) &WebContents::GetNavigationEntryAtIndex)
.SetMethod("_historyLength", &WebContents::GetHistoryLength) .SetMethod("_historyLength", &WebContents::GetHistoryLength)
.SetMethod("clearHistory", &WebContents::ClearHistory) .SetMethod("_clearHistory", &WebContents::ClearHistory)
.SetMethod("isCrashed", &WebContents::IsCrashed) .SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("forcefullyCrashRenderer", .SetMethod("forcefullyCrashRenderer",
&WebContents::ForcefullyCrashRenderer) &WebContents::ForcefullyCrashRenderer)

View file

@ -567,6 +567,84 @@ describe('webContents module', () => {
w = new BrowserWindow({ show: false }); w = new BrowserWindow({ show: false });
}); });
afterEach(closeAllWindows); afterEach(closeAllWindows);
describe('navigationHistory.canGoBack and navigationHistory.goBack API', () => {
it('should not be able to go back if history is empty', async () => {
expect(w.webContents.navigationHistory.canGoBack()).to.be.false();
});
it('should be able to go back if history is not empty', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(1);
expect(w.webContents.navigationHistory.canGoBack()).to.be.true();
w.webContents.navigationHistory.goBack();
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(0);
});
});
describe('navigationHistory.canGoForward and navigationHistory.goForward API', () => {
it('should not be able to go forward if history is empty', async () => {
expect(w.webContents.navigationHistory.canGoForward()).to.be.false();
});
it('should not be able to go forward if current index is same as history length', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
expect(w.webContents.navigationHistory.canGoForward()).to.be.false();
});
it('should be able to go forward if history is not empty and active index is less than history length', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
w.webContents.navigationHistory.goBack();
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(0);
expect(w.webContents.navigationHistory.canGoForward()).to.be.true();
w.webContents.navigationHistory.goForward();
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(1);
});
});
describe('navigationHistory.canGoToOffset(index) and navigationHistory.goToOffset(index) API', () => {
it('should not be able to go to invalid offset', async () => {
expect(w.webContents.navigationHistory.canGoToOffset(-1)).to.be.false();
expect(w.webContents.navigationHistory.canGoToOffset(10)).to.be.false();
});
it('should be able to go to valid negative offset', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
await w.loadURL(urlPage3);
expect(w.webContents.navigationHistory.canGoToOffset(-2)).to.be.true();
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(2);
w.webContents.navigationHistory.goToOffset(-2);
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(0);
});
it('should be able to go to valid positive offset', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
await w.loadURL(urlPage3);
w.webContents.navigationHistory.goBack();
expect(w.webContents.navigationHistory.canGoToOffset(1)).to.be.true();
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(1);
w.webContents.navigationHistory.goToOffset(1);
expect(w.webContents.navigationHistory.getActiveIndex()).to.equal(2);
});
});
describe('navigationHistory.clear API', () => {
it('should be able clear history', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
await w.loadURL(urlPage3);
expect(w.webContents.navigationHistory.length()).to.equal(3);
w.webContents.navigationHistory.clear();
expect(w.webContents.navigationHistory.length()).to.equal(1);
});
});
describe('navigationHistory.getEntryAtIndex(index) API ', () => { describe('navigationHistory.getEntryAtIndex(index) API ', () => {
it('should fetch default navigation entry when no urls are loaded', async () => { it('should fetch default navigation entry when no urls are loaded', async () => {
const result = w.webContents.navigationHistory.getEntryAtIndex(0); const result = w.webContents.navigationHistory.getEntryAtIndex(0);

View file

@ -88,6 +88,14 @@ declare namespace Electron {
_getNavigationEntryAtIndex(index: number): Electron.EntryAtIndex | null; _getNavigationEntryAtIndex(index: number): Electron.EntryAtIndex | null;
_getActiveIndex(): number; _getActiveIndex(): number;
_historyLength(): number; _historyLength(): number;
_canGoBack(): boolean;
_canGoForward(): boolean;
_canGoToOffset(): boolean;
_goBack(): void;
_goForward(): void;
_goToOffset(index: number): void;
_goToIndex(index: number): void;
_clearHistory():void
canGoToIndex(index: number): boolean; canGoToIndex(index: number): boolean;
destroy(): void; destroy(): void;
// <webview> // <webview>