Skip to content
This repository was archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
Merge pull request #9154 from brave/navigation-state2
Browse files Browse the repository at this point in the history
Navigation state
  • Loading branch information
bbondy committed Jun 9, 2017
1 parent f1ab997 commit b332d8e
Show file tree
Hide file tree
Showing 32 changed files with 846 additions and 385 deletions.
2 changes: 1 addition & 1 deletion app/browser/reducers/flashReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const flashReducer = (state, action, immutableAction) => {
const location = action.get('location')
const settings = siteSettings.getSiteSettingsForURL(state.get('siteSettings'), location)
if (!(settings && ['boolean', 'number'].includes(typeof settings.get('flash')))) {
flash.showFlashMessageBox(location, action.get('senderTabId'))
flash.showFlashMessageBox(location, action.get('tabId'))
}
break
}
Expand Down
15 changes: 15 additions & 0 deletions app/browser/reducers/tabsReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const {getWebContents} = require('../webContentsCache')
const {BrowserWindow} = require('electron')
const tabState = require('../../common/state/tabState')
const windowState = require('../../common/state/windowState')
const tabActions = require('../../common/actions/tabActions')
const windowConstants = require('../../../js/constants/windowConstants')
const windowActions = require('../../../js/actions/windowActions')
const {makeImmutable} = require('../../common/state/immutableUtil')
Expand Down Expand Up @@ -77,6 +78,20 @@ const updateActiveTab = (state, closeTabId) => {
const tabsReducer = (state, action, immutableAction) => {
action = immutableAction || makeImmutable(action)
switch (action.get('actionType')) {
case tabActions.didStartNavigation.name:
case tabActions.didFinishNavigation.name:
{
state = tabState.setNavigationState(state, action.get('tabId'), action.get('navigationState'))
break
}
case tabActions.reload.name:
{
const tabId = tabState.resolveTabId(state, action.get('tabId'))
setImmediate(() => {
tabs.reload(tabId, action.get('ignoreCache'))
})
break
}
case appConstants.APP_SET_STATE:
state = tabs.init(state, action)
break
Expand Down
120 changes: 111 additions & 9 deletions app/browser/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

const appActions = require('../../js/actions/appActions')
const windowActions = require('../../js/actions/windowActions')
const tabActions = require('../common/actions/tabActions')
const config = require('../../js/constants/config')
const Immutable = require('immutable')
const tabState = require('../common/state/tabState')
const {app, BrowserWindow, extensions, session, ipcMain} = require('electron')
const {makeImmutable} = require('../common/state/immutableUtil')
const {getTargetAboutUrl, getSourceAboutUrl, isSourceAboutUrl, newFrameUrl, isTargetAboutUrl} = require('../../js/lib/appUrlUtil')
const {isURL, getUrlFromInput, toPDFJSLocation, getDefaultFaviconUrl, isHttpOrHttps} = require('../../js/lib/urlutil')
const {getTargetAboutUrl, getSourceAboutUrl, isSourceAboutUrl, newFrameUrl, isTargetAboutUrl, isIntermediateAboutPage, isTargetMagnetUrl, getSourceMagnetUrl} = require('../../js/lib/appUrlUtil')
const {isURL, getUrlFromInput, toPDFJSLocation, getDefaultFaviconUrl, isHttpOrHttps, getLocationIfPDF} = require('../../js/lib/urlutil')
const {isSessionPartition} = require('../../js/state/frameStateUtil')
const {getOrigin} = require('../../js/state/siteUtil')
const {getSetting} = require('../../js/settings')
Expand Down Expand Up @@ -283,6 +284,57 @@ const updateAboutDetails = (tab, tabValue) => {
}
}

// hack to deal with about:* pages
const fixDisplayURL = (navigationEntry, controller) => {
if (navigationEntry == null) {
return null
}

navigationEntry = Object.assign({}, navigationEntry)

navigationEntry.virtualURL = getLocationIfPDF(navigationEntry.virtualURL)

if (isTargetAboutUrl(navigationEntry.virtualURL)) {
navigationEntry.virtualURL = getSourceAboutUrl(navigationEntry.virtualURL)
}

if (isIntermediateAboutPage(navigationEntry.virtualURL)) {
const previousEntry = controller.getEntryAtOffset(-1)
if (!controller.canGoForward() && previousEntry) {
navigationEntry.virtualURL = previousEntry.virtualURL
}
}

if (isTargetMagnetUrl(navigationEntry.virtualURL)) {
navigationEntry.virtualURL = getSourceMagnetUrl(navigationEntry.virtualURL)
}

if (navigationEntry.virtualURL === 'about:newtab') {
navigationEntry.virtualURL = ''
}

navigationEntry.virtualURL = muon.url.formatForDisplay(navigationEntry.virtualURL)

const parsedURL = muon.url.parse(navigationEntry.virtualURL)
navigationEntry = Object.assign(parsedURL, navigationEntry)

return navigationEntry
}

const createNavigationState = (navigationHandle, controller) => {
return Immutable.Map({
hasCommitted: navigationHandle.hasCommitted(),
isErrorPage: navigationHandle.isErrorPage(),
netErrorCode: navigationHandle.getNetErrorCode(),
activeEntry: fixDisplayURL(controller.getActiveEntry(), controller),
visibleEntry: fixDisplayURL(controller.getVisibleEntry(), controller),
lastCommittedEntry: fixDisplayURL(controller.getLastCommittedEntry(), controller),
pendingEntry: fixDisplayURL(controller.getPendingEntry(), controller),
canGoBack: controller.canGoBack(),
canGoForward: controller.canGoForward()
})
}

const api = {
init: (state, action) => {
process.on('open-url-from-tab', (e, source, targetUrl, disposition) => {
Expand All @@ -308,14 +360,17 @@ const api = {
return
}

let location = newTab.getURL()
if (!location || location === '') {
location = 'about:blank'
}
let displayURL = newTab.getURL()
let location = displayURL || 'about:blank'

const openerTabId = !source.isDestroyed() ? source.getId() : -1
let newTabValue = getTabValue(newTab.getId())

let rendererInitiated = false
if (source.isGuest()) {
rendererInitiated = true
}

let index
if (parseInt(newTabValue.get('index')) > -1) {
index = newTabValue.get('index')
Expand All @@ -331,6 +386,8 @@ const api = {

const frameOpts = {
location,
displayURL,
rendererInitiated,
partition: newTab.session.partition,
active: !!newTabValue.get('active'),
guestInstanceId: newTab.guestInstanceId,
Expand Down Expand Up @@ -369,6 +426,34 @@ const api = {
}
let tabId = tab.getId()

tab.on('did-start-navigation', (e, navigationHandle) => {
if (navigationHandle.isValid() && navigationHandle.isInMainFrame()) {
const controller = tab.controller()
if (!controller.isValid()) {
return
}
let tabValue = getTabValue(tabId)
if (tabValue) {
const windowId = tabValue.get('windowId')
tabActions.didStartNavigation(tabId, createNavigationState(navigationHandle, controller), windowId)
}
}
})

tab.on('did-finish-navigation', (e, navigationHandle) => {
if (navigationHandle.isValid() && navigationHandle.isInMainFrame()) {
const controller = tab.controller()
if (!controller.isValid()) {
return
}
let tabValue = getTabValue(tabId)
if (tabValue) {
const windowId = tabValue.get('windowId')
tabActions.didFinishNavigation(tabId, createNavigationState(navigationHandle, controller), windowId)
}
}
})

tab.on('unresponsive', () => {
console.log('unresponsive')
})
Expand Down Expand Up @@ -453,6 +538,18 @@ const api = {
}
},

reload: (tabId, ignoreCache = false) => {
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
// TODO(bridiver) - removeEntryAtIndex for intermediate about pages after loading
if (isIntermediateAboutPage(getSourceAboutUrl(tab.getURL()))) {
tab.goToOffset(-1)
} else {
tab.reload(ignoreCache)
}
}
},

loadURL: (action) => {
action = makeImmutable(action)
const tabId = action.get('tabId')
Expand Down Expand Up @@ -675,20 +772,25 @@ const api = {
goBack: (tabId) => {
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
tab.goBack()
// TODO(bridiver) - removeEntryAtIndex for intermediate about pages after loading
if (tab.controller().canGoToOffset(-2) && isIntermediateAboutPage(getSourceAboutUrl(tab.getURL()))) {
tab.goToOffset(-2)
} else if (tab.controller().canGoBack()) {
tab.goBack()
}
}
},

goForward: (tabId) => {
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
if (tab && !tab.isDestroyed() && tab.canGoForward()) {
tab.goForward()
}
},

goToIndex: (tabId, index) => {
const tab = getWebContents(tabId)
if (tab && !tab.isDestroyed()) {
if (tab && !tab.isDestroyed() && tab.canGoToIndex(index)) {
tab.goToIndex(index)
}
},
Expand Down
40 changes: 40 additions & 0 deletions app/common/actions/tabActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

'use strict'

const dispatchAction = require('../../common/dispatcher/dispatchAction')

const tabActions = {
// TODO(bridiver) - this is an action anti-pattern and the code that uses it should be refactored
// to be declarative
reload: function tabActionsReload (tabId, ignoreCache) {
dispatchAction(tabActions.reload.name, {
tabId,
ignoreCache
})
},

didFinishNavigation: function tabActionsDidFinishNavigation (tabId, navigationState, windowId) {
dispatchAction(tabActions.didFinishNavigation.name, {
tabId,
navigationState,
queryInfo: {
windowId
}
})
},

didStartNavigation: function tabActionsDidStartNavigation (tabId, navigationState, windowId) {
dispatchAction(tabActions.didFinishNavigation.name, {
tabId,
navigationState,
queryInfo: {
windowId
}
})
}
}

module.exports = tabActions
17 changes: 17 additions & 0 deletions app/common/dispatcher/dispatchAction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = function (name, action) {
action = Object.assign({
actionType: name
}, action)

if (typeof chrome !== 'undefined' && typeof chrome.ipcRenderer === 'object') {
chrome.ipcRenderer.send('dispatch-action', JSON.stringify(action))
} else if (typeof process !== 'undefined') {
if (process.type === 'browser' && typeof process.emit === 'function') {
process.emit('dispatch-action', action)
} else if (process.type === 'worker' && typeof postMessage === 'function') {
postMessage({message: 'dispatch-action', action})
}
} else {
throw new Error('Unsupported environment for dispatch')
}
}
29 changes: 29 additions & 0 deletions app/common/state/tabState.js
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,35 @@ const tabState = {
state = tabState.removeTabField(state, 'frame')
state = state.delete('tabsInternal')
return state.delete('tabs')
},

setNavigationState: (state, tabId, navigationState) => {
const tabValue = tabState.getByTabId(state, tabId)
if (!tabValue) {
return state
}
const path = tabState.getPathByTabId(state, tabId).push('navigationState')
return state.setIn(path, navigationState)
},

getNavigationState: (state, tabId) => {
const path = tabState.getPathByTabId(state, tabId)
return path ? state.getIn(path.push('navigationState'), Immutable.Map()) : null
},

getVisibleEntry: (state, tabId) => {
const navigationState = tabState.getNavigationState(state, tabId)
return navigationState ? navigationState.get('visibleEntry', '') : null
},

getVisibleURL: (state, tabId) => {
const entry = tabState.getVisibleEntry(state, tabId)
return entry ? entry.get('url') : ''
},

getVisibleVirtualURL: (state, tabId) => {
const entry = tabState.getVisibleEntry(state, tabId)
return entry ? entry.get('virtualURL') : ''
}
}

Expand Down
13 changes: 4 additions & 9 deletions app/renderer/components/frame/frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const ipc = require('electron').ipcRenderer

// Actions
const appActions = require('../../../../js/actions/appActions')
const tabActions = require('../../../common/actions/tabActions')
const windowActions = require('../../../../js/actions/windowActions')
const webviewActions = require('../../../../js/actions/webviewActions')
const getSetting = require('../../../../js/settings').getSetting
Expand Down Expand Up @@ -316,17 +317,12 @@ class Frame extends React.Component {
!this.isAboutPage() &&
!isTorrentViewerURL(this.props.location)) {
this.webview.loadURL(this.props.location)
} else if (this.isIntermediateAboutPage() &&
this.props.tabUrl !== this.props.location &&
this.props.tabUrl !== this.props.aboutDetailsUrl) {
appActions.loadURLRequested(this.props.aboutDetailsUrl,
this.props.aboutDetailsFrameKey)
} else {
this.webview.reload()
tabActions.reload(this.props.tabId)
}
break
case 'clean-reload':
this.webview.reloadIgnoringCache()
tabActions.reload(this.props.tabId, true)
break
case 'explicitLoadURL':
this.webview.loadURL(this.props.location)
Expand Down Expand Up @@ -595,7 +591,7 @@ class Frame extends React.Component {
method = () => {
this.reloadCounter[this.props.location] = this.reloadCounter[this.props.location] || 0
if (this.reloadCounter[this.props.location] < 2) {
this.webview.reload()
tabActions.reload(this.props.tabId)
this.reloadCounter[this.props.location] = this.reloadCounter[this.props.location] + 1
}
}
Expand Down Expand Up @@ -703,7 +699,6 @@ class Frame extends React.Component {
appActions.removeSite(siteUtil.getDetailFromFrame(this.frame))
} else if (isAborted(e.errorCode)) {
// just stay put
windowActions.navigationAborted(this.props.tabId, url)
} else if (provisionLoadFailure) {
windowActions.setNavigated(url, this.props.frameKey, true, this.props.tabId)
}
Expand Down
7 changes: 2 additions & 5 deletions app/renderer/components/main/noScriptInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
const React = require('react')
const PropTypes = require('prop-types')
const Immutable = require('immutable')
const ipc = require('electron').ipcRenderer
const urlParse = require('../../../common/urlParse')

// Components
Expand All @@ -15,9 +14,7 @@ const BrowserButton = require('../common/browserButton')

// Actions
const appActions = require('../../../../js/actions/appActions')

// Constants
const messages = require('../../../../js/constants/messages')
const tabActions = require('../../../common/actions/tabActions')

// Utils
const siteUtil = require('../../../../js/state/siteUtil')
Expand Down Expand Up @@ -77,7 +74,7 @@ class NoScriptInfo extends ImmutableComponent {
}

reload () {
ipc.emit(messages.SHORTCUT_ACTIVE_FRAME_CLEAN_RELOAD)
tabActions.reload(this.props.frameProps.get('tabId'))
}

onAllow (setting, e) {
Expand Down
Loading

0 comments on commit b332d8e

Please sign in to comment.