electron/lib/browser/api/navigation-controller.js

172 lines
5.1 KiB
JavaScript
Raw Normal View History

'use strict'
2018-09-13 16:10:51 +00:00
const { ipcMain } = require('electron')
2016-01-12 02:40:23 +00:00
2016-01-14 18:35:29 +00:00
// The history operation in renderer is redirected to browser.
ipcMain.on('ELECTRON_NAVIGATION_CONTROLLER', function (event, method, ...args) {
event.sender[method](...args)
})
2016-01-12 02:40:23 +00:00
ipcMain.on('ELECTRON_SYNC_NAVIGATION_CONTROLLER', function (event, method, ...args) {
event.returnValue = event.sender[method](...args)
})
2016-01-12 02:40:23 +00:00
2016-01-14 18:44:21 +00:00
// JavaScript implementation of Chromium's NavigationController.
// Instead of relying on Chromium for history control, we compeletely do history
// control on user land, and only rely on WebContents.loadURL for navigation.
// This helps us avoid Chromium's various optimizations so we can ensure renderer
// process is restarted everytime.
const NavigationController = (function () {
function NavigationController (webContents) {
this.webContents = webContents
this.clearHistory()
2016-01-12 02:40:23 +00:00
// webContents may have already navigated to a page.
if (this.webContents._getURL()) {
this.currentIndex++
this.history.push(this.webContents._getURL())
}
this.webContents.on('navigation-entry-commited', (event, url, inPage, replaceEntry) => {
if (this.inPageIndex > -1 && !inPage) {
// Navigated to a new page, clear in-page mark.
this.inPageIndex = -1
} else if (this.inPageIndex === -1 && inPage && !replaceEntry) {
// Started in-page navigations.
this.inPageIndex = this.currentIndex
}
if (this.pendingIndex >= 0) {
// Go to index.
this.currentIndex = this.pendingIndex
this.pendingIndex = -1
2016-03-29 00:35:49 +00:00
this.history[this.currentIndex] = url
} else if (replaceEntry) {
// Non-user initialized navigation.
2016-03-29 00:35:49 +00:00
this.history[this.currentIndex] = url
} else {
// Normal navigation. Clear history.
this.history = this.history.slice(0, this.currentIndex + 1)
this.currentIndex++
this.history.push(url)
}
})
2016-01-12 02:40:23 +00:00
}
NavigationController.prototype.loadURL = function (url, options) {
2016-01-12 02:40:23 +00:00
if (options == null) {
options = {}
2016-01-12 02:40:23 +00:00
}
this.pendingIndex = -1
this.webContents._loadURL(url, options)
return this.webContents.emit('load-url', url, options)
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.getURL = function () {
2016-01-12 02:40:23 +00:00
if (this.currentIndex === -1) {
return ''
2016-01-12 02:40:23 +00:00
} else {
return this.history[this.currentIndex]
2016-01-12 02:40:23 +00:00
}
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.stop = function () {
this.pendingIndex = -1
return this.webContents._stop()
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.reload = function () {
this.pendingIndex = this.currentIndex
return this.webContents._loadURL(this.getURL(), {})
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.reloadIgnoringCache = function () {
this.pendingIndex = this.currentIndex
2016-01-12 02:40:23 +00:00
return this.webContents._loadURL(this.getURL(), {
extraHeaders: 'pragma: no-cache\n'
})
}
NavigationController.prototype.canGoBack = function () {
return this.getActiveIndex() > 0
}
NavigationController.prototype.canGoForward = function () {
return this.getActiveIndex() < this.history.length - 1
}
NavigationController.prototype.canGoToIndex = function (index) {
return index >= 0 && index < this.history.length
}
NavigationController.prototype.canGoToOffset = function (offset) {
return this.canGoToIndex(this.currentIndex + offset)
}
NavigationController.prototype.clearHistory = function () {
this.history = []
this.currentIndex = -1
this.pendingIndex = -1
2016-03-29 00:35:49 +00:00
this.inPageIndex = -1
}
NavigationController.prototype.goBack = function () {
2016-01-12 02:40:23 +00:00
if (!this.canGoBack()) {
return
2016-01-12 02:40:23 +00:00
}
this.pendingIndex = this.getActiveIndex() - 1
2016-01-12 02:40:23 +00:00
if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
return this.webContents._goBack()
2016-01-12 02:40:23 +00:00
} else {
return this.webContents._loadURL(this.history[this.pendingIndex], {})
2016-01-12 02:40:23 +00:00
}
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.goForward = function () {
2016-01-12 02:40:23 +00:00
if (!this.canGoForward()) {
return
2016-01-12 02:40:23 +00:00
}
this.pendingIndex = this.getActiveIndex() + 1
2016-01-12 02:40:23 +00:00
if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
return this.webContents._goForward()
2016-01-12 02:40:23 +00:00
} else {
return this.webContents._loadURL(this.history[this.pendingIndex], {})
2016-01-12 02:40:23 +00:00
}
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.goToIndex = function (index) {
2016-01-12 02:40:23 +00:00
if (!this.canGoToIndex(index)) {
return
2016-01-12 02:40:23 +00:00
}
this.pendingIndex = index
return this.webContents._loadURL(this.history[this.pendingIndex], {})
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.goToOffset = function (offset) {
2016-01-12 02:40:23 +00:00
if (!this.canGoToOffset(offset)) {
return
2016-01-12 02:40:23 +00:00
}
const pendingIndex = this.currentIndex + offset
2016-01-12 02:40:23 +00:00
if (this.inPageIndex > -1 && pendingIndex >= this.inPageIndex) {
this.pendingIndex = pendingIndex
return this.webContents._goToOffset(offset)
2016-01-12 02:40:23 +00:00
} else {
return this.goToIndex(pendingIndex)
2016-01-12 02:40:23 +00:00
}
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.getActiveIndex = function () {
2016-01-12 02:40:23 +00:00
if (this.pendingIndex === -1) {
return this.currentIndex
2016-01-12 02:40:23 +00:00
} else {
return this.pendingIndex
2016-01-12 02:40:23 +00:00
}
}
2016-01-12 02:40:23 +00:00
NavigationController.prototype.length = function () {
return this.history.length
}
2016-01-12 02:40:23 +00:00
return NavigationController
})()
2016-01-12 02:40:23 +00:00
module.exports = NavigationController