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

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

Merged
merged 12 commits into from
Jun 5, 2024
38 changes: 38 additions & 0 deletions docs/api/navigation-history.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ Each navigation entry corresponds to a specific page. The indexing system follow

### 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 `offset`.
alicelovescake marked this conversation as resolved.
Show resolved Hide resolved

#### `navigationHistory.clear()`

Clears the navigation history.

#### `navigationHistory.getActiveIndex()`

Returns `Integer` - The index of the current page, from which we would go back/forward or reload.
Expand All @@ -24,6 +42,26 @@ Returns `Object`:

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()`

Returns `Integer` - History length.
32 changes: 24 additions & 8 deletions docs/api/web-contents.md
Original file line number Diff line number Diff line change
Expand Up @@ -1126,44 +1126,60 @@ Reloads the current web page.

Reloads current page and ignores cache.

#### `contents.canGoBack()`
#### `contents.canGoBack()` _Deprecated_

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.

#### `contents.canGoToOffset(offset)`
**Deprecated:** Should use the new [`contents.navigationHistory.canGoForward`](navigation-history.md#navigationhistorycangoforward) API.

#### `contents.canGoToOffset(offset)` _Deprecated_

* `offset` Integer

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.
alicelovescake marked this conversation as resolved.
Show resolved Hide resolved

#### `contents.clearHistory()` _Deprecated_

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.

#### `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.

#### `contents.goToIndex(index)`
**Deprecated:** Should use the new [`contents.navigationHistory.goForward`](navigation-history.md#navigationhistorygoforward) API.

#### `contents.goToIndex(index)` _Deprecated_

* `index` Integer

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.
alicelovescake marked this conversation as resolved.
Show resolved Hide resolved

#### `contents.goToOffset(offset)` _Deprecated_

* `offset` Integer

Navigates to the specified offset from the "current entry".

**Deprecated:** Should use the new [`contents.navigationHistory.goToOffset`](navigation-history.md#navigationhistorygotooffsetoffset) API.
alicelovescake marked this conversation as resolved.
Show resolved Hide resolved

#### `contents.isCrashed()`

Returns `boolean` - Whether the renderer process has crashed.
Expand Down
56 changes: 56 additions & 0 deletions lib/browser/api/web-contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,54 @@ const environment = process._linkedBinding('electron_common_environment');
const loggingEnabled = () => {
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.
WebContents.prototype._init = function () {
Expand Down Expand Up @@ -537,6 +585,14 @@ WebContents.prototype._init = function () {
// maintaining a list of navigation entries for backward and forward navigation.
Object.defineProperty(this, 'navigationHistory', {
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),
length: this._historyLength.bind(this),
getEntryAtIndex: this._getNavigationEntryAtIndex.bind(this)
Expand Down
16 changes: 8 additions & 8 deletions shell/browser/api/electron_api_web_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4276,19 +4276,19 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
.SetMethod("isLoadingMainFrame", &WebContents::IsLoadingMainFrame)
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
.SetMethod("stop", &WebContents::Stop)
.SetMethod("canGoBack", &WebContents::CanGoBack)
.SetMethod("goBack", &WebContents::GoBack)
.SetMethod("canGoForward", &WebContents::CanGoForward)
.SetMethod("goForward", &WebContents::GoForward)
.SetMethod("canGoToOffset", &WebContents::CanGoToOffset)
.SetMethod("goToOffset", &WebContents::GoToOffset)
.SetMethod("_canGoBack", &WebContents::CanGoBack)
.SetMethod("_goBack", &WebContents::GoBack)
.SetMethod("_canGoForward", &WebContents::CanGoForward)
.SetMethod("_goForward", &WebContents::GoForward)
.SetMethod("_canGoToOffset", &WebContents::CanGoToOffset)
.SetMethod("_goToOffset", &WebContents::GoToOffset)
.SetMethod("canGoToIndex", &WebContents::CanGoToIndex)
.SetMethod("goToIndex", &WebContents::GoToIndex)
.SetMethod("_goToIndex", &WebContents::GoToIndex)
.SetMethod("_getActiveIndex", &WebContents::GetActiveIndex)
.SetMethod("_getNavigationEntryAtIndex",
&WebContents::GetNavigationEntryAtIndex)
.SetMethod("_historyLength", &WebContents::GetHistoryLength)
.SetMethod("clearHistory", &WebContents::ClearHistory)
.SetMethod("_clearHistory", &WebContents::ClearHistory)
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("forcefullyCrashRenderer",
&WebContents::ForcefullyCrashRenderer)
Expand Down
78 changes: 78 additions & 0 deletions spec/api-web-contents-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,84 @@ describe('webContents module', () => {
w = new BrowserWindow({ show: false });
});
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 ', () => {
it('should fetch default navigation entry when no urls are loaded', async () => {
const result = w.webContents.navigationHistory.getEntryAtIndex(0);
Expand Down
8 changes: 8 additions & 0 deletions typings/internal-electron.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ declare namespace Electron {
_getNavigationEntryAtIndex(index: number): Electron.EntryAtIndex | null;
_getActiveIndex(): 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;
destroy(): void;
// <webview>
Expand Down