From 0143a4548869c1e8201ef3c3b6c2e098d5dd5140 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sun, 26 Apr 2015 21:28:30 +0800 Subject: [PATCH] Implement our own NavigationController --- atom/browser/api/atom_api_web_contents.cc | 63 ++----------------- atom/browser/api/atom_api_web_contents.h | 11 +--- atom/browser/api/lib/navigation-controller.coffee | 76 +++++++++++++++++++++++ atom/browser/api/lib/web-contents.coffee | 11 ++-- filenames.gypi | 1 + 5 files changed, 89 insertions(+), 73 deletions(-) create mode 100644 atom/browser/api/lib/navigation-controller.coffee diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5853b10..4e27e1e 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -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) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 4ccf3d8..371c338 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -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; diff --git a/atom/browser/api/lib/navigation-controller.coffee b/atom/browser/api/lib/navigation-controller.coffee new file mode 100644 index 0000000..8f193de --- /dev/null +++ b/atom/browser/api/lib/navigation-controller.coffee @@ -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 diff --git a/atom/browser/api/lib/web-contents.coffee b/atom/browser/api/lib/web-contents.coffee index cb772fd..e249ccf 100644 --- a/atom/browser/api/lib/web-contents.coffee +++ b/atom/browser/api/lib/web-contents.coffee @@ -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) -> diff --git a/filenames.gypi b/filenames.gypi index 586d67c..0931368 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -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', -- 2.7.4