Skip to content
This repository has been archived by the owner on Jan 4, 2019. It is now read-only.

Commit

Permalink
let the navigation controller manage history
Browse files Browse the repository at this point in the history
  • Loading branch information
bridiver committed Jun 8, 2016
1 parent 04b032e commit 43b0d42
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 215 deletions.
9 changes: 7 additions & 2 deletions atom/browser/api/atom_api_extension.cc
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,18 @@ bool Extension::IsBackgroundPageUrl(GURL url,
}

// static
bool Extension::IsBackgroundPage(WebContents* web_contents) {
auto browser_context = web_contents->web_contents()->GetBrowserContext();
bool Extension::IsBackgroundPageWebContents(content::WebContents* web_contents) {
auto browser_context = web_contents->GetBrowserContext();
auto url = web_contents->GetURL();

return IsBackgroundPageUrl(url, browser_context);
}

// static
bool Extension::IsBackgroundPage(WebContents* web_contents) {
return IsBackgroundPageWebContents(web_contents->web_contents());
}

// static
v8::Local<v8::Value> Extension::TabValue(v8::Isolate* isolate,
WebContents* web_contents) {
Expand Down
1 change: 1 addition & 0 deletions atom/browser/api/atom_api_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class Extension : public content::NotificationObserver {

static bool IsBackgroundPageUrl(GURL url,
content::BrowserContext* browser_context);
static bool IsBackgroundPageWebContents(content::WebContents* web_contents);
static bool IsBackgroundPage(WebContents* web_contents);

static v8::Local<v8::Value> TabValue(v8::Isolate* isolate,
Expand Down
81 changes: 71 additions & 10 deletions atom/browser/api/atom_api_web_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ WebContents::WebContents(v8::Isolate* isolate,
if (is_guest) {
guest_delegate_.reset(new WebViewGuestDelegate);
create_params.guest_delegate = guest_delegate_.get();
if (!params)
create_params.site_instance = content::SiteInstance::CreateForURL(
session->browser_context(), GURL("chrome-guest://fake-host"));
}
web_contents = content::WebContents::Create(create_params);

Expand Down Expand Up @@ -988,18 +991,67 @@ void WebContents::Stop() {
}

void WebContents::GoBack() {
atom::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
web_contents()->GetController().GoBack();
if (web_contents()->GetController().CanGoBack()) {
atom::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
web_contents()->GetController().GoBack();
}
}

void WebContents::GoForward() {
atom::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
web_contents()->GetController().GoForward();
if (web_contents()->GetController().CanGoForward()) {
atom::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
web_contents()->GetController().GoForward();
}
}

void WebContents::GoToOffset(int offset) {
if (web_contents()->GetController().CanGoToOffset(offset)) {
atom::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
web_contents()->GetController().GoToOffset(offset);
}
}

void WebContents::GoToIndex(int index) {
atom::AtomBrowserClient::SuppressRendererProcessRestartForOnce();
web_contents()->GetController().GoToOffset(offset);
web_contents()->GetController().GoToIndex(index);
}

bool WebContents::CanGoToOffset(int offset) const {
return web_contents()->GetController().CanGoToOffset(offset);
}

bool WebContents::CanGoBack() const {
return web_contents()->GetController().CanGoBack();
}

bool WebContents::CanGoForward() const {
return web_contents()->GetController().CanGoForward();
}

int WebContents::GetCurrentEntryIndex() const {
return web_contents()->GetController().GetCurrentEntryIndex();
}

int WebContents::GetLastCommittedEntryIndex() const {
return web_contents()->GetController().GetLastCommittedEntryIndex();
}

int WebContents::GetEntryCount() const {
return web_contents()->GetController().GetEntryCount();
}

const GURL& WebContents::GetURLAtIndex(int index) const {
auto entry = web_contents()->GetController().GetEntryAtIndex(index);
if (entry)
return entry->GetURL();
else return GURL::EmptyGURL();
}

void WebContents::ShowRepostFormWarningDialog(content::WebContents* source) {
if (Emit("repost-form-warning"))
source->GetController().CancelPendingReload();
else
source->GetController().ContinuePendingReload();
}

bool WebContents::IsCrashed() const {
Expand Down Expand Up @@ -1402,15 +1454,24 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("_loadURL", &WebContents::LoadURL)
.SetMethod("_reload", &WebContents::Reload)
.SetMethod("downloadURL", &WebContents::DownloadURL)
.SetMethod("_getURL", &WebContents::GetURL)
.SetMethod("getURL", &WebContents::GetURL)
.SetMethod("getTitle", &WebContents::GetTitle)
.SetMethod("isLoading", &WebContents::IsLoading)
.SetMethod("isLoadingMainFrame", &WebContents::IsLoadingMainFrame)
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
.SetMethod("_stop", &WebContents::Stop)
.SetMethod("_goBack", &WebContents::GoBack)
.SetMethod("_goForward", &WebContents::GoForward)
.SetMethod("_goToOffset", &WebContents::GoToOffset)
.SetMethod("stop", &WebContents::Stop)
.SetMethod("goBack", &WebContents::GoBack)
.SetMethod("goForward", &WebContents::GoForward)
.SetMethod("goToOffset", &WebContents::GoToOffset)
.SetMethod("goToIndex", &WebContents::GoToIndex)
.SetMethod("canGoBack", &WebContents::CanGoBack)
.SetMethod("canGoForward", &WebContents::CanGoForward)
.SetMethod("canGoToOffset", &WebContents::CanGoToOffset)
.SetMethod("getURLAtIndex", &WebContents::GetURLAtIndex)
.SetMethod("getEntryCount", &WebContents::GetEntryCount)
.SetMethod("getCurrentEntryIndex", &WebContents::GetCurrentEntryIndex)
.SetMethod("getLastCommittedEntryIndex",
&WebContents::GetLastCommittedEntryIndex)
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
Expand Down
9 changes: 9 additions & 0 deletions atom/browser/api/atom_api_web_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ class WebContents : public mate::TrackableObject<WebContents>,
void GoBack();
void GoForward();
void GoToOffset(int offset);
bool CanGoToOffset(int offset) const;
bool CanGoBack() const;
bool CanGoForward() const;
void GoToIndex(int index);
const GURL& GetURLAtIndex(int index) const;
int GetCurrentEntryIndex() const;
int GetLastCommittedEntryIndex() const;
int GetEntryCount() const;
void ShowRepostFormWarningDialog(content::WebContents* source) override;
bool IsCrashed() const;
void SetUserAgent(const std::string& user_agent);
std::string GetUserAgent();
Expand Down
9 changes: 3 additions & 6 deletions atom/browser/web_contents_preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <vector>

#include "atom/browser/api/atom_api_extension.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/values.h"
Expand Down Expand Up @@ -52,14 +53,10 @@ class WebContentsPreferences
#endif
return !(
// node integration is disabled
cmd_line->GetSwitchValueASCII(switches::kNodeIntegration) == "false" &&
cmd_line->GetSwitchValueASCII(switches::kNodeIntegration) != "true" &&
// and there is no preload script
!cmd_line->HasSwitch(switches::kPreloadScript) &&
!cmd_line->HasSwitch(switches::kPreloadURL) &&
// and this is a guest renderer process
(cmd_line->GetSwitchValueASCII(::switches::kProcessType) ==
::switches::kRendererProcess &&
cmd_line->HasSwitch(switches::kGuestInstanceID)));
!cmd_line->HasSwitch(switches::kPreloadURL));
}

static bool run_node() {
Expand Down
21 changes: 0 additions & 21 deletions atom/common/api/resources/ipc_bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,6 @@ exports.didCreateDocumentElement = function() {
window.confirm = function(message, title) {
return ipc.sendSync('window-confirm', message, title);
};

// copied from override.js
// TODO(bridiver) is this even necessary? I don't think we need
// or want these navigation controller hacks for nodeless renderers
var sendHistoryOperation = function() {
var args;
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
return ipc.send.apply(ipc, ['ELECTRON_NAVIGATION_CONTROLLER'].concat(slice.call(args)));
};

window.history.back = function() {
return sendHistoryOperation('goBack');
};

window.history.forward = function() {
return sendHistoryOperation('goForward');
};

window.history.go = function(offset) {
return sendHistoryOperation('goToOffset', offset);
};
};

exports.binding = ipc;
147 changes: 0 additions & 147 deletions lib/browser/api/navigation-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,174 +2,27 @@

const {ipcMain} = require('electron')

// The history operation in renderer is redirected to browser.
ipcMain.on('ELECTRON_NAVIGATION_CONTROLLER', function (event, method, ...args) {
var ref
(ref = event.sender)[method].apply(ref, args)
})

ipcMain.on('ELECTRON_SYNC_NAVIGATION_CONTROLLER', function (event, method, ...args) {
var ref
event.returnValue = (ref = event.sender)[method].apply(ref, 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.
var NavigationController = (function () {
function NavigationController (webContents) {
this.webContents = webContents
this.clearHistory()

// 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) => {
var currentEntry
if (this.inPageIndex > -1 && !inPage) {
// Navigated to a new page, clear in-page mark.
this.inPageIndex = -1
} else if (this.inPageIndex === -1 && inPage) {
// Started in-page navigations.
this.inPageIndex = this.currentIndex
}
if (this.pendingIndex >= 0) {
// Go to index.
this.currentIndex = this.pendingIndex
this.pendingIndex = -1
this.history[this.currentIndex] = url
} else if (replaceEntry) {
// Non-user initialized navigation.
this.history[this.currentIndex] = url
} else {
// Normal navigation. Clear history.
this.history = this.history.slice(0, this.currentIndex + 1)
currentEntry = this.history[this.currentIndex]
if ((currentEntry != null ? currentEntry.url : void 0) !== url) {
this.currentIndex++
return this.history.push(url)
}
}
})
}

NavigationController.prototype.loadURL = function (url, options) {
if (options == null) {
options = {}
}
this.pendingIndex = -1
this.webContents._loadURL(url, options)
return this.webContents.emit('load-url', url, options)
}

NavigationController.prototype.getURL = function () {
if (this.currentIndex === -1) {
return ''
} else {
return this.history[this.currentIndex]
}
}

NavigationController.prototype.stop = function () {
this.pendingIndex = -1
return this.webContents._stop()
}

NavigationController.prototype.reload = function () {
this.pendingIndex = this.currentIndex
return this.webContents._reload(false)
}

NavigationController.prototype.reloadIgnoringCache = function () {
this.pendingIndex = this.currentIndex
return this.webContents._reload(true)
}

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
this.inPageIndex = -1
}

NavigationController.prototype.goBack = function () {
if (!this.canGoBack()) {
return
}
this.pendingIndex = this.getActiveIndex() - 1
if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
return this.webContents._goBack()
} else {
return this.webContents._loadURL(this.history[this.pendingIndex], {})
}
}

NavigationController.prototype.goForward = function () {
if (!this.canGoForward()) {
return
}
this.pendingIndex = this.getActiveIndex() + 1
if (this.inPageIndex > -1 && this.pendingIndex >= this.inPageIndex) {
return this.webContents._goForward()
} else {
return this.webContents._loadURL(this.history[this.pendingIndex], {})
}
}

NavigationController.prototype.goToIndex = function (index) {
if (!this.canGoToIndex(index)) {
return
}
this.pendingIndex = index
return this.webContents._loadURL(this.history[this.pendingIndex], {})
}

NavigationController.prototype.goToOffset = function (offset) {
var pendingIndex
if (!this.canGoToOffset(offset)) {
return
}
pendingIndex = this.currentIndex + offset
if (this.inPageIndex > -1 && pendingIndex >= this.inPageIndex) {
this.pendingIndex = pendingIndex
return this.webContents._goToOffset(offset)
} else {
return this.goToIndex(pendingIndex)
}
}

NavigationController.prototype.getActiveIndex = function () {
if (this.pendingIndex === -1) {
return this.currentIndex
} else {
return this.pendingIndex
}
}

NavigationController.prototype.length = function () {
return this.history.length
}

return NavigationController
})()

Expand Down
3 changes: 2 additions & 1 deletion lib/browser/guest-view-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ let supportedWebViewEvents = [
'update-target-url',
'load-progress-changed',
'set-active',
'context-menu'
'context-menu',
'repost-form-warning'
]

let nextInstanceId = 0
Expand Down
Loading

0 comments on commit 43b0d42

Please sign in to comment.