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 "atom/common/native_mate_converters/value_converter.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "brightray/browser/inspectable_web_contents.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/favicon_status.h"
|
||||||
#include "content/public/browser/navigation_details.h"
|
#include "content/public/browser/navigation_details.h"
|
||||||
#include "content/public/browser/navigation_entry.h"
|
#include "content/public/browser/navigation_entry.h"
|
||||||
|
@ -30,7 +31,6 @@
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
#include "native_mate/object_template_builder.h"
|
#include "native_mate/object_template_builder.h"
|
||||||
#include "vendor/brightray/browser/media/media_stream_devices_controller.h"
|
|
||||||
|
|
||||||
#include "atom/common/node_includes.h"
|
#include "atom/common/node_includes.h"
|
||||||
|
|
||||||
|
@ -312,8 +312,7 @@ void WebContents::WebContentsDestroyed() {
|
||||||
|
|
||||||
void WebContents::NavigationEntryCommitted(
|
void WebContents::NavigationEntryCommitted(
|
||||||
const content::LoadCommittedDetails& load_details) {
|
const content::LoadCommittedDetails& load_details) {
|
||||||
auto entry = web_contents()->GetController().GetLastCommittedEntry();
|
Emit("navigation-entry-commited", load_details.entry->GetURL());
|
||||||
entry->SetVirtualURL(load_details.entry->GetOriginalRequestURL());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::DidAttach(int guest_proxy_routing_id) {
|
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);
|
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 {
|
base::string16 WebContents::GetTitle() const {
|
||||||
return web_contents()->GetTitle();
|
return web_contents()->GetTitle();
|
||||||
}
|
}
|
||||||
|
@ -415,46 +407,8 @@ void WebContents::Stop() {
|
||||||
web_contents()->Stop();
|
web_contents()->Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::Reload(const mate::Dictionary& options) {
|
void WebContents::ReloadIgnoringCache() {
|
||||||
// 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.
|
|
||||||
web_contents()->GetController().ReloadIgnoringCache(false);
|
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 {
|
int WebContents::GetRoutingID() const {
|
||||||
|
@ -599,21 +553,12 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||||
.SetMethod("destroy", &WebContents::Destroy)
|
.SetMethod("destroy", &WebContents::Destroy)
|
||||||
.SetMethod("isAlive", &WebContents::IsAlive)
|
.SetMethod("isAlive", &WebContents::IsAlive)
|
||||||
.SetMethod("_loadUrl", &WebContents::LoadURL)
|
.SetMethod("_loadUrl", &WebContents::LoadURL)
|
||||||
.SetMethod("getUrl", &WebContents::GetURL)
|
|
||||||
.SetMethod("getTitle", &WebContents::GetTitle)
|
.SetMethod("getTitle", &WebContents::GetTitle)
|
||||||
.SetMethod("getFavicon", &WebContents::GetFavicon)
|
.SetMethod("getFavicon", &WebContents::GetFavicon)
|
||||||
.SetMethod("isLoading", &WebContents::IsLoading)
|
.SetMethod("isLoading", &WebContents::IsLoading)
|
||||||
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
||||||
.SetMethod("stop", &WebContents::Stop)
|
.SetMethod("_stop", &WebContents::Stop)
|
||||||
.SetMethod("_reload", &WebContents::Reload)
|
|
||||||
.SetMethod("_reloadIgnoringCache", &WebContents::ReloadIgnoringCache)
|
.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("getRoutingId", &WebContents::GetRoutingID)
|
||||||
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
||||||
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
||||||
|
|
|
@ -47,21 +47,12 @@ class WebContents : public mate::EventEmitter,
|
||||||
void Destroy();
|
void Destroy();
|
||||||
bool IsAlive() const;
|
bool IsAlive() const;
|
||||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||||
GURL GetURL() const;
|
|
||||||
base::string16 GetTitle() const;
|
base::string16 GetTitle() const;
|
||||||
gfx::Image GetFavicon() const;
|
gfx::Image GetFavicon() const;
|
||||||
bool IsLoading() const;
|
bool IsLoading() const;
|
||||||
bool IsWaitingForResponse() const;
|
bool IsWaitingForResponse() const;
|
||||||
void Stop();
|
void Stop();
|
||||||
void Reload(const mate::Dictionary& options);
|
void ReloadIgnoringCache();
|
||||||
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);
|
|
||||||
int GetRoutingID() const;
|
int GetRoutingID() const;
|
||||||
int GetProcessID() const;
|
int GetProcessID() const;
|
||||||
bool IsCrashed() 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
|
EventEmitter = require('events').EventEmitter
|
||||||
|
NavigationController = require './navigation-controller'
|
||||||
binding = process.atomBinding 'web_contents'
|
binding = process.atomBinding 'web_contents'
|
||||||
ipc = require 'ipc'
|
ipc = require 'ipc'
|
||||||
|
|
||||||
|
@ -26,10 +27,12 @@ module.exports.wrap = (webContents) ->
|
||||||
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
|
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
|
||||||
webContents.equal = (other) -> @getId() is other.getId()
|
webContents.equal = (other) -> @getId() is other.getId()
|
||||||
|
|
||||||
# Provide a default parameter for |urlOptions|.
|
# The navigation controller.
|
||||||
webContents.loadUrl = (url, urlOptions={}) -> @_loadUrl url, urlOptions
|
controller = new NavigationController(webContents)
|
||||||
webContents.reload = (urlOptions={}) -> @_reload urlOptions
|
webContents.controller = controller
|
||||||
webContents.reloadIgnoringCache = (urlOptions={}) -> @_reloadIgnoringCache urlOptions
|
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.
|
# Translate |disposition| to string for 'new-window' event.
|
||||||
webContents.on '-new-window', (args..., disposition) ->
|
webContents.on '-new-window', (args..., disposition) ->
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
'atom/browser/api/lib/ipc.coffee',
|
'atom/browser/api/lib/ipc.coffee',
|
||||||
'atom/browser/api/lib/menu.coffee',
|
'atom/browser/api/lib/menu.coffee',
|
||||||
'atom/browser/api/lib/menu-item.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/power-monitor.coffee',
|
||||||
'atom/browser/api/lib/protocol.coffee',
|
'atom/browser/api/lib/protocol.coffee',
|
||||||
'atom/browser/api/lib/screen.coffee',
|
'atom/browser/api/lib/screen.coffee',
|
||||||
|
|
Loading…
Add table
Reference in a new issue