Implement our own NavigationController
This commit is contained in:
parent
2f1683445b
commit
0143a45488
5 changed files with 89 additions and 73 deletions
|
@ -18,6 +18,7 @@
|
|||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/media/media_stream_devices_controller.h"
|
||||
#include "content/public/browser/favicon_status.h"
|
||||
#include "content/public/browser/navigation_details.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
|
@ -30,7 +31,6 @@
|
|||
#include "content/public/browser/web_contents.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "vendor/brightray/browser/media/media_stream_devices_controller.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
|
@ -312,8 +312,7 @@ void WebContents::WebContentsDestroyed() {
|
|||
|
||||
void WebContents::NavigationEntryCommitted(
|
||||
const content::LoadCommittedDetails& load_details) {
|
||||
auto entry = web_contents()->GetController().GetLastCommittedEntry();
|
||||
entry->SetVirtualURL(load_details.entry->GetOriginalRequestURL());
|
||||
Emit("navigation-entry-commited", load_details.entry->GetURL());
|
||||
}
|
||||
|
||||
void WebContents::DidAttach(int guest_proxy_routing_id) {
|
||||
|
@ -385,13 +384,6 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
|||
web_contents()->GetController().LoadURLWithParams(params);
|
||||
}
|
||||
|
||||
GURL WebContents::GetURL() const {
|
||||
auto entry = web_contents()->GetController().GetLastCommittedEntry();
|
||||
if (!entry)
|
||||
return GURL::EmptyGURL();
|
||||
return entry->GetVirtualURL();
|
||||
}
|
||||
|
||||
base::string16 WebContents::GetTitle() const {
|
||||
return web_contents()->GetTitle();
|
||||
}
|
||||
|
@ -415,46 +407,8 @@ void WebContents::Stop() {
|
|||
web_contents()->Stop();
|
||||
}
|
||||
|
||||
void WebContents::Reload(const mate::Dictionary& options) {
|
||||
// Navigating to a URL would always restart the renderer process, we want this
|
||||
// because normal reloading will break our node integration.
|
||||
// This is done by AtomBrowserClient::ShouldSwapProcessesForNavigation.
|
||||
LoadURL(GetURL(), options);
|
||||
}
|
||||
|
||||
void WebContents::ReloadIgnoringCache(const mate::Dictionary& options) {
|
||||
// Hack to remove pending entries that ignores cache and treated as a fresh
|
||||
// load.
|
||||
void WebContents::ReloadIgnoringCache() {
|
||||
web_contents()->GetController().ReloadIgnoringCache(false);
|
||||
Reload(options);
|
||||
}
|
||||
|
||||
bool WebContents::CanGoBack() const {
|
||||
return web_contents()->GetController().CanGoBack();
|
||||
}
|
||||
|
||||
bool WebContents::CanGoForward() const {
|
||||
return web_contents()->GetController().CanGoForward();
|
||||
}
|
||||
|
||||
bool WebContents::CanGoToOffset(int offset) const {
|
||||
return web_contents()->GetController().CanGoToOffset(offset);
|
||||
}
|
||||
|
||||
void WebContents::GoBack() {
|
||||
web_contents()->GetController().GoBack();
|
||||
}
|
||||
|
||||
void WebContents::GoForward() {
|
||||
web_contents()->GetController().GoForward();
|
||||
}
|
||||
|
||||
void WebContents::GoToIndex(int index) {
|
||||
web_contents()->GetController().GoToIndex(index);
|
||||
}
|
||||
|
||||
void WebContents::GoToOffset(int offset) {
|
||||
web_contents()->GetController().GoToOffset(offset);
|
||||
}
|
||||
|
||||
int WebContents::GetRoutingID() const {
|
||||
|
@ -599,21 +553,12 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
|||
.SetMethod("destroy", &WebContents::Destroy)
|
||||
.SetMethod("isAlive", &WebContents::IsAlive)
|
||||
.SetMethod("_loadUrl", &WebContents::LoadURL)
|
||||
.SetMethod("getUrl", &WebContents::GetURL)
|
||||
.SetMethod("getTitle", &WebContents::GetTitle)
|
||||
.SetMethod("getFavicon", &WebContents::GetFavicon)
|
||||
.SetMethod("isLoading", &WebContents::IsLoading)
|
||||
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
||||
.SetMethod("stop", &WebContents::Stop)
|
||||
.SetMethod("_reload", &WebContents::Reload)
|
||||
.SetMethod("_stop", &WebContents::Stop)
|
||||
.SetMethod("_reloadIgnoringCache", &WebContents::ReloadIgnoringCache)
|
||||
.SetMethod("canGoBack", &WebContents::CanGoBack)
|
||||
.SetMethod("canGoForward", &WebContents::CanGoForward)
|
||||
.SetMethod("canGoToOffset", &WebContents::CanGoToOffset)
|
||||
.SetMethod("goBack", &WebContents::GoBack)
|
||||
.SetMethod("goForward", &WebContents::GoForward)
|
||||
.SetMethod("goToIndex", &WebContents::GoToIndex)
|
||||
.SetMethod("goToOffset", &WebContents::GoToOffset)
|
||||
.SetMethod("getRoutingId", &WebContents::GetRoutingID)
|
||||
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
||||
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
||||
|
|
|
@ -47,21 +47,12 @@ class WebContents : public mate::EventEmitter,
|
|||
void Destroy();
|
||||
bool IsAlive() const;
|
||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||
GURL GetURL() const;
|
||||
base::string16 GetTitle() const;
|
||||
gfx::Image GetFavicon() const;
|
||||
bool IsLoading() const;
|
||||
bool IsWaitingForResponse() const;
|
||||
void Stop();
|
||||
void Reload(const mate::Dictionary& options);
|
||||
void ReloadIgnoringCache(const mate::Dictionary& options);
|
||||
bool CanGoBack() const;
|
||||
bool CanGoForward() const;
|
||||
bool CanGoToOffset(int offset) const;
|
||||
void GoBack();
|
||||
void GoForward();
|
||||
void GoToIndex(int index);
|
||||
void GoToOffset(int offset);
|
||||
void ReloadIgnoringCache();
|
||||
int GetRoutingID() const;
|
||||
int GetProcessID() const;
|
||||
bool IsCrashed() const;
|
||||
|
|
76
atom/browser/api/lib/navigation-controller.coffee
Normal file
76
atom/browser/api/lib/navigation-controller.coffee
Normal file
|
@ -0,0 +1,76 @@
|
|||
# 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) ->
|
||||
@history = []
|
||||
@currentIndex = -1
|
||||
@pendingIndex = -1
|
||||
|
||||
@webContents.on 'navigation-entry-commited', (event, url) =>
|
||||
if @pendingIndex >= 0 # Go to index.
|
||||
@currentIndex = @pendingIndex
|
||||
@pendingIndex = -1
|
||||
@history[@currentIndex] = url
|
||||
else # Normal navigation.
|
||||
@history = @history.slice 0, @currentIndex + 1 # Clear history.
|
||||
if @history[@currentIndex] isnt url
|
||||
@currentIndex++
|
||||
@history.push url
|
||||
|
||||
loadUrl: (url, options={}) ->
|
||||
@pendingIndex = -1
|
||||
@webContents._loadUrl 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: ->
|
||||
@currentIndex > 0
|
||||
|
||||
canGoForward: ->
|
||||
@currentIndex < @history.length
|
||||
|
||||
canGoToIndex: (index) ->
|
||||
index >=0 and index < @history.length
|
||||
|
||||
canGoToOffset: (offset) ->
|
||||
@canGoToIndex @currentIndex + offset
|
||||
|
||||
goBack: ->
|
||||
return unless @canGoBack()
|
||||
@pendingIndex = @currentIndex - 1
|
||||
@webContents._loadUrl @history[@pendingIndex], {}
|
||||
|
||||
goForward: ->
|
||||
return unless @canGoForward()
|
||||
@pendingIndex = @currentIndex + 1
|
||||
@webContents._loadUrl @history[@pendingIndex], {}
|
||||
|
||||
goToIndex: (index) ->
|
||||
return unless @canGoToIndex index
|
||||
@pendingIndex = index
|
||||
@webContents._loadUrl @history[@pendingIndex], {}
|
||||
|
||||
goToOffset: (offset) ->
|
||||
return unless @canGoToOffset offset
|
||||
@goToIndex @currentIndex + offset
|
||||
|
||||
module.exports = NavigationController
|
|
@ -1,4 +1,5 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
NavigationController = require './navigation-controller'
|
||||
binding = process.atomBinding 'web_contents'
|
||||
ipc = require 'ipc'
|
||||
|
||||
|
@ -26,10 +27,12 @@ module.exports.wrap = (webContents) ->
|
|||
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
|
||||
webContents.equal = (other) -> @getId() is other.getId()
|
||||
|
||||
# Provide a default parameter for |urlOptions|.
|
||||
webContents.loadUrl = (url, urlOptions={}) -> @_loadUrl url, urlOptions
|
||||
webContents.reload = (urlOptions={}) -> @_reload urlOptions
|
||||
webContents.reloadIgnoringCache = (urlOptions={}) -> @_reloadIgnoringCache urlOptions
|
||||
# The navigation controller.
|
||||
controller = new NavigationController(webContents)
|
||||
webContents.controller = controller
|
||||
for name, method of NavigationController.prototype when method instanceof Function
|
||||
do (name, method) ->
|
||||
webContents[name] = -> method.apply controller, arguments
|
||||
|
||||
# Translate |disposition| to string for 'new-window' event.
|
||||
webContents.on '-new-window', (args..., disposition) ->
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
'atom/browser/api/lib/ipc.coffee',
|
||||
'atom/browser/api/lib/menu.coffee',
|
||||
'atom/browser/api/lib/menu-item.coffee',
|
||||
'atom/browser/api/lib/navigation-controller.coffee',
|
||||
'atom/browser/api/lib/power-monitor.coffee',
|
||||
'atom/browser/api/lib/protocol.coffee',
|
||||
'atom/browser/api/lib/screen.coffee',
|
||||
|
|
Loading…
Add table
Reference in a new issue