ipc = require 'ipc' # The history operation in renderer is redirected to browser. ipc.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) -> event.sender[method] args... ipc.on 'ATOM_SHELL_SYNC_NAVIGATION_CONTROLLER', (event, method, args...) -> event.returnValue = event.sender[method] args... # 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. class NavigationController constructor: (@webContents) -> @clearHistory() @webContents.on 'navigation-entry-commited', (event, url, inPage, replaceEntry) => if @inPageIndex > -1 and not inPage # Navigated to a new page, clear in-page mark. @inPageIndex = -1 else if @inPageIndex is -1 and inPage # Started in-page navigations. @inPageIndex = @currentIndex if @pendingIndex >= 0 # Go to index. @currentIndex = @pendingIndex @pendingIndex = -1 @history[@currentIndex] = url else if replaceEntry # Non-user initialized navigation. @history[@currentIndex] = url else # Normal navigation. @history = @history.slice 0, @currentIndex + 1 # Clear history. currentEntry = @history[@currentIndex] if currentEntry?.url isnt url @currentIndex++ @history.push url loadUrl: (url, options={}) -> @pendingIndex = -1 @webContents._loadUrl url, options @webContents.emit 'load-url', url, options getUrl: -> if @currentIndex is -1 '' else @history[@currentIndex] stop: -> @pendingIndex = -1 @webContents._stop() reload: -> @pendingIndex = @currentIndex @webContents._loadUrl @getUrl(), {} reloadIgnoringCache: -> @webContents._reloadIgnoringCache() # Rely on WebContents to clear cache. @reload() canGoBack: -> @getActiveIndex() > 0 canGoForward: -> @getActiveIndex() < @history.length - 1 canGoToIndex: (index) -> index >=0 and index < @history.length canGoToOffset: (offset) -> @canGoToIndex @currentIndex + offset clearHistory: -> @history = [] @currentIndex = -1 @pendingIndex = -1 @inPageIndex = -1 goBack: -> return unless @canGoBack() @pendingIndex = @getActiveIndex() - 1 if @inPageIndex > -1 and @pendingIndex >= @inPageIndex @webContents._goBack() else @webContents._loadUrl @history[@pendingIndex], {} goForward: -> return unless @canGoForward() @pendingIndex = @getActiveIndex() + 1 if @inPageIndex > -1 and @pendingIndex >= @inPageIndex @webContents._goForward() else @webContents._loadUrl @history[@pendingIndex], {} goToIndex: (index) -> return unless @canGoToIndex index @pendingIndex = index @webContents._loadUrl @history[@pendingIndex], {} goToOffset: (offset) -> return unless @canGoToOffset offset pendingIndex = @currentIndex + offset if @inPageIndex > -1 and pendingIndex >= @inPageIndex @pendingIndex = pendingIndex @webContents._goToOffset offset else @goToIndex pendingIndex getActiveIndex: -> if @pendingIndex is -1 then @currentIndex else @pendingIndex length: -> @history.length module.exports = NavigationController