From a47fe715d13531b3c41276ff00b728d265f47740 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 8 Jun 2017 02:12:52 +0200 Subject: [PATCH 1/4] pass ref part of url to allow #page= for pdf viewer --- atom/browser/atom_web_ui_controller_factory.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/atom/browser/atom_web_ui_controller_factory.cc b/atom/browser/atom_web_ui_controller_factory.cc index a73eed19a115..ef8b2785ae55 100644 --- a/atom/browser/atom_web_ui_controller_factory.cc +++ b/atom/browser/atom_web_ui_controller_factory.cc @@ -57,6 +57,9 @@ AtomWebUIControllerFactory::CreateWebUIControllerForURL(content::WebUI* web_ui, src = param.second; } } + if (url.has_ref()) { + src = src + '#' + url.ref(); + } auto browser_context = web_ui->GetWebContents()->GetBrowserContext(); return new PdfViewerUI(browser_context, web_ui, src); } From 0f4341da42f886aaab5e15d280254457efa77a17 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 8 Jun 2017 02:13:49 +0200 Subject: [PATCH 2/4] add zoom behaviour code from chromium and make pdf viewer use manual zoom behaviour to match chromium --- atom/browser/ui/webui/pdf_viewer_handler.cc | 49 ++++--- atom/browser/ui/webui/pdf_viewer_handler.h | 10 +- atom/browser/web_contents_zoom_controller.cc | 145 +++++++++++++++++-- atom/browser/web_contents_zoom_controller.h | 40 +++++ 4 files changed, 210 insertions(+), 34 deletions(-) diff --git a/atom/browser/ui/webui/pdf_viewer_handler.cc b/atom/browser/ui/webui/pdf_viewer_handler.cc index 5829b59f6d32..699119fb2802 100644 --- a/atom/browser/ui/webui/pdf_viewer_handler.cc +++ b/atom/browser/ui/webui/pdf_viewer_handler.cc @@ -8,6 +8,9 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/values.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" #include "content/public/browser/stream_handle.h" #include "content/public/browser/stream_info.h" #include "content/public/browser/web_contents.h" @@ -90,15 +93,15 @@ void PdfViewerHandler::RegisterMessages() { } void PdfViewerHandler::OnJavascriptAllowed() { - auto host_zoom_map = - content::HostZoomMap::GetForWebContents(web_ui()->GetWebContents()); - host_zoom_map_subscription_ = - host_zoom_map->AddZoomLevelChangedCallback(base::Bind( - &PdfViewerHandler::OnZoomLevelChanged, base::Unretained(this))); + auto zoom_controller = WebContentsZoomController::FromWebContents( + web_ui()->GetWebContents()); + zoom_controller->AddObserver(this); } void PdfViewerHandler::OnJavascriptDisallowed() { - host_zoom_map_subscription_.reset(); + auto zoom_controller = WebContentsZoomController::FromWebContents( + web_ui()->GetWebContents()); + zoom_controller->RemoveObserver(this); } void PdfViewerHandler::Initialize(const base::ListValue* args) { @@ -116,6 +119,11 @@ void PdfViewerHandler::Initialize(const base::ListValue* args) { } else { initialize_callback_id_ = callback_id->CreateDeepCopy(); } + + auto zoom_controller = WebContentsZoomController::FromWebContents( + web_ui()->GetWebContents()); + zoom_controller->SetZoomMode(WebContentsZoomController::ZOOM_MODE_MANUAL); + zoom_controller->SetZoomLevel(0); } void PdfViewerHandler::GetDefaultZoom(const base::ListValue* args) { @@ -125,9 +133,9 @@ void PdfViewerHandler::GetDefaultZoom(const base::ListValue* args) { const base::Value* callback_id; CHECK(args->Get(0, &callback_id)); - auto host_zoom_map = - content::HostZoomMap::GetForWebContents(web_ui()->GetWebContents()); - double zoom_level = host_zoom_map->GetDefaultZoomLevel(); + auto zoom_controller = WebContentsZoomController::FromWebContents( + web_ui()->GetWebContents()); + double zoom_level = zoom_controller->GetDefaultZoomLevel(); ResolveJavascriptCallback( *callback_id, base::Value(content::ZoomLevelToZoomFactor(zoom_level))); @@ -140,8 +148,9 @@ void PdfViewerHandler::GetInitialZoom(const base::ListValue* args) { const base::Value* callback_id; CHECK(args->Get(0, &callback_id)); - double zoom_level = - content::HostZoomMap::GetZoomLevel(web_ui()->GetWebContents()); + auto zoom_controller = WebContentsZoomController::FromWebContents( + web_ui()->GetWebContents()); + double zoom_level = zoom_controller->GetZoomLevel(); ResolveJavascriptCallback( *callback_id, base::Value(content::ZoomLevelToZoomFactor(zoom_level))); @@ -156,8 +165,9 @@ void PdfViewerHandler::SetZoom(const base::ListValue* args) { double zoom_level = 0.0; CHECK(args->GetDouble(1, &zoom_level)); - content::HostZoomMap::SetZoomLevel(web_ui()->GetWebContents(), - zoom_level); + auto zoom_controller = WebContentsZoomController::FromWebContents( + web_ui()->GetWebContents()); + zoom_controller->SetZoomLevel(zoom_level); ResolveJavascriptCallback(*callback_id, base::Value(zoom_level)); } @@ -198,13 +208,12 @@ void PdfViewerHandler::Reload(const base::ListValue* args) { web_ui()->GetWebContents()->ReloadFocusedFrame(false); } -void PdfViewerHandler::OnZoomLevelChanged( - const content::HostZoomMap::ZoomLevelChange& change) { - if (change.host == kPdfViewerUIHost) { - CallJavascriptFunction( - "cr.webUIListenerCallback", base::StringValue("onZoomLevelChanged"), - base::Value( - content::ZoomLevelToZoomFactor(change.zoom_level))); +void PdfViewerHandler::OnZoomLevelChanged(content::WebContents* web_contents, + double level, bool is_temporary) { + if (web_ui()->GetWebContents() == web_contents) { + CallJavascriptFunction("cr.webUIListenerCallback", + base::StringValue("onZoomLevelChanged"), + base::Value(content::ZoomLevelToZoomFactor(level))); } } diff --git a/atom/browser/ui/webui/pdf_viewer_handler.h b/atom/browser/ui/webui/pdf_viewer_handler.h index 7576b06c851e..46e7ac8d4edc 100644 --- a/atom/browser/ui/webui/pdf_viewer_handler.h +++ b/atom/browser/ui/webui/pdf_viewer_handler.h @@ -7,6 +7,7 @@ #include +#include "atom/browser/web_contents_zoom_controller.h" #include "base/macros.h" #include "content/public/browser/host_zoom_map.h" #include "content/public/browser/web_ui_message_handler.h" @@ -21,7 +22,8 @@ struct StreamInfo; namespace atom { -class PdfViewerHandler : public content::WebUIMessageHandler { +class PdfViewerHandler : public content::WebUIMessageHandler, + public WebContentsZoomController::Observer { public: explicit PdfViewerHandler(const std::string& original_url); ~PdfViewerHandler() override; @@ -41,11 +43,9 @@ class PdfViewerHandler : public content::WebUIMessageHandler { void SetZoom(const base::ListValue* args); void GetStrings(const base::ListValue* args); void Reload(const base::ListValue* args); - void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change); + void OnZoomLevelChanged(content::WebContents* web_contents, double level, + bool is_temporary); - // Keeps track of events related to zooming. - std::unique_ptr - host_zoom_map_subscription_; std::unique_ptr initialize_callback_id_; content::StreamInfo* stream_; std::string original_url_; diff --git a/atom/browser/web_contents_zoom_controller.cc b/atom/browser/web_contents_zoom_controller.cc index f48e643d96a6..764fa939784c 100644 --- a/atom/browser/web_contents_zoom_controller.cc +++ b/atom/browser/web_contents_zoom_controller.cc @@ -21,6 +21,8 @@ namespace atom { WebContentsZoomController::WebContentsZoomController( content::WebContents* web_contents) : content::WebContentsObserver(web_contents), + zoom_mode_(ZOOM_MODE_DEFAULT), + zoom_level_(1.0), old_process_id_(-1), old_view_id_(-1), embedder_zoom_controller_(nullptr) { @@ -47,24 +49,44 @@ void WebContentsZoomController::SetEmbedderZoomController( void WebContentsZoomController::SetZoomLevel(double level) { if (!web_contents()->GetRenderViewHost()->IsRenderViewLive() || - content::ZoomValuesEqual(GetZoomLevel(), level)) + content::ZoomValuesEqual(GetZoomLevel(), level) || + zoom_mode_ == ZOOM_MODE_DISABLED) return; int render_process_id = web_contents()->GetRenderProcessHost()->GetID(); int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID(); - if (host_zoom_map_->UsesTemporaryZoomLevel(render_process_id, - render_view_id)) { - host_zoom_map_->ClearTemporaryZoomLevel(render_process_id, render_view_id); + + if (zoom_mode_ == ZOOM_MODE_MANUAL) { + zoom_level_ = level; + + for (Observer& observer : observers_) + observer.OnZoomLevelChanged(web_contents(), level, true); + + return; } - content::HostZoomMap::SetZoomLevel(web_contents(), level); - // Notify observers of zoom level changes. - for (Observer& observer : observers_) - observer.OnZoomLevelChanged(web_contents(), level, false); + content::HostZoomMap* zoom_map = + content::HostZoomMap::GetForWebContents(web_contents()); + if (zoom_mode_ == ZOOM_MODE_ISOLATED || + zoom_map->UsesTemporaryZoomLevel(render_process_id, render_view_id)) { + zoom_map->SetTemporaryZoomLevel( + render_process_id, render_view_id, level); + // Notify observers of zoom level changes. + for (Observer& observer : observers_) + observer.OnZoomLevelChanged(web_contents(), level, true); + } else { + content::HostZoomMap::SetZoomLevel(web_contents(), level); + + // Notify observers of zoom level changes. + for (Observer& observer : observers_) + observer.OnZoomLevelChanged(web_contents(), level, false); + } } double WebContentsZoomController::GetZoomLevel() { - return content::HostZoomMap::GetZoomLevel(web_contents()); + return zoom_mode_ == ZOOM_MODE_MANUAL + ? zoom_level_ + : content::HostZoomMap::GetZoomLevel(web_contents()); } void WebContentsZoomController::SetDefaultZoomFactor(double factor) { @@ -91,6 +113,110 @@ bool WebContentsZoomController::UsesTemporaryZoomLevel() { render_view_id); } + +void WebContentsZoomController::SetZoomMode(ZoomMode new_mode) { + if (new_mode == zoom_mode_) + return; + + content::HostZoomMap* zoom_map = + content::HostZoomMap::GetForWebContents(web_contents()); + int render_process_id = web_contents()->GetRenderProcessHost()->GetID(); + int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID(); + double original_zoom_level = GetZoomLevel(); + + switch (new_mode) { + case ZOOM_MODE_DEFAULT: { + content::NavigationEntry* entry = + web_contents()->GetController().GetLastCommittedEntry(); + + if (entry) { + GURL url = content::HostZoomMap::GetURLFromEntry(entry); + std::string host = net::GetHostOrSpecFromURL(url); + + if (zoom_map->HasZoomLevel(url.scheme(), host)) { + // If there are other tabs with the same origin, then set this tab's + // zoom level to match theirs. The temporary zoom level will be + // cleared below, but this call will make sure this tab re-draws at + // the correct zoom level. + double origin_zoom_level = + zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), host); + zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id, + origin_zoom_level); + } else { + // The host will need a level prior to removing the temporary level. + // We don't want the zoom level to change just because we entered + // default mode. + zoom_map->SetZoomLevelForHost(host, original_zoom_level); + } + } + // Remove per-tab zoom data for this tab. No event callback expected. + zoom_map->ClearTemporaryZoomLevel(render_process_id, render_view_id); + break; + } + case ZOOM_MODE_ISOLATED: { + // Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the + // page needs an initial isolated zoom back to the same level it was at + // in the other mode. + if (zoom_mode_ != ZOOM_MODE_DISABLED) { + zoom_map->SetTemporaryZoomLevel(render_process_id, render_view_id, + original_zoom_level); + } else { + // When we don't call any HostZoomMap set functions, we send the event + // manually. + for (Observer& observer : observers_) + observer.OnZoomLevelChanged(web_contents(), original_zoom_level, + false); + } + break; + } + case ZOOM_MODE_MANUAL: { + // Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the + // page needs to be resized to the default zoom. While in manual mode, + // the zoom level is handled independently. + if (zoom_mode_ != ZOOM_MODE_DISABLED) { + zoom_map->SetTemporaryZoomLevel( + render_process_id, render_view_id, GetDefaultZoomLevel()); + zoom_level_ = original_zoom_level; + } else { + // When we don't call any HostZoomMap set functions, we send the event + // manually. + for (Observer& observer : observers_) + observer.OnZoomLevelChanged(web_contents(), original_zoom_level, + false); + } + break; + } + case ZOOM_MODE_DISABLED: { + // The page needs to be zoomed back to default before disabling the zoom + zoom_map->SetTemporaryZoomLevel( + render_process_id, render_view_id, GetDefaultZoomLevel()); + break; + } + } + + zoom_mode_ = new_mode; +} + + +void WebContentsZoomController::ResetZoomModeOnNavigationIfNeeded( + const GURL& url) { + if (zoom_mode_ != ZOOM_MODE_ISOLATED && zoom_mode_ != ZOOM_MODE_MANUAL) + return; + + int render_process_id = web_contents()->GetRenderProcessHost()->GetID(); + int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID(); + content::HostZoomMap* zoom_map = + content::HostZoomMap::GetForWebContents(web_contents()); + zoom_level_ = zoom_map->GetDefaultZoomLevel(); + double new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme( + url.scheme(), net::GetHostOrSpecFromURL(url)); + for (Observer& observer : observers_) + observer.OnZoomLevelChanged(web_contents(), new_zoom_level, + false); + zoom_map->ClearTemporaryZoomLevel(render_process_id, render_view_id); + zoom_mode_ = ZOOM_MODE_DEFAULT; +} + void WebContentsZoomController::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted()) @@ -101,6 +227,7 @@ void WebContentsZoomController::DidFinishNavigation( return; } + ResetZoomModeOnNavigationIfNeeded(navigation_handle->GetURL()); SetZoomFactorOnNavigationIfNeeded(navigation_handle->GetURL()); } diff --git a/atom/browser/web_contents_zoom_controller.h b/atom/browser/web_contents_zoom_controller.h index a0d28ad9b998..493219c09410 100644 --- a/atom/browser/web_contents_zoom_controller.h +++ b/atom/browser/web_contents_zoom_controller.h @@ -28,6 +28,26 @@ class WebContentsZoomController protected: virtual ~Observer() {} }; + + // Defines how zoom changes are handled. + enum ZoomMode { + // Results in default zoom behavior, i.e. zoom changes are handled + // automatically and on a per-origin basis, meaning that other tabs + // navigated to the same origin will also zoom. + ZOOM_MODE_DEFAULT, + // Results in zoom changes being handled automatically, but on a per-tab + // basis. Tabs in this zoom mode will not be affected by zoom changes in + // other tabs, and vice versa. + ZOOM_MODE_ISOLATED, + // Overrides the automatic handling of zoom changes. The |onZoomChange| + // event will still be dispatched, but the page will not actually be zoomed. + // These zoom changes can be handled manually by listening for the + // |onZoomChange| event. Zooming in this mode is also on a per-tab basis. + ZOOM_MODE_MANUAL, + // Disables all zooming in this tab. The tab will revert to the default + // zoom level, and all attempted zoom changes will be ignored. + ZOOM_MODE_DISABLED, + }; explicit WebContentsZoomController(content::WebContents* web_contents); ~WebContentsZoomController() override; @@ -45,6 +65,20 @@ class WebContentsZoomController void SetTemporaryZoomLevel(double level); bool UsesTemporaryZoomLevel(); + // Sets the zoom mode, which defines zoom behavior (see enum ZoomMode). + void SetZoomMode(ZoomMode zoom_mode); + + void ResetZoomModeOnNavigationIfNeeded(const GURL& url); + + ZoomMode zoom_mode() const { return zoom_mode_; } + + // Convenience method to get default zoom level. Implemented here for + // inlining. + double GetDefaultZoomLevel() const { + return content::HostZoomMap::GetForWebContents(web_contents()) + ->GetDefaultZoomLevel(); + } + protected: // content::WebContentsObserver: void DidFinishNavigation(content::NavigationHandle* handle) override; @@ -58,6 +92,12 @@ class WebContentsZoomController // Called after a navigation has committed to set default zoom factor. void SetZoomFactorOnNavigationIfNeeded(const GURL& url); + // The current zoom mode. + ZoomMode zoom_mode_; + + // Current zoom level. + double zoom_level_; + // kZoomFactor. double default_zoom_factor_; double temporary_zoom_level_; From f8d3b363ea391d966f4d2ba99a47f44b9642ee05 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 8 Jun 2017 09:57:24 +0200 Subject: [PATCH 3/4] :art: lint fix --- atom/browser/ui/webui/pdf_viewer_handler.cc | 4 ++-- atom/browser/ui/webui/pdf_viewer_handler.h | 2 +- atom/browser/web_contents_zoom_controller.cc | 8 ++++---- atom/browser/web_contents_zoom_controller.h | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atom/browser/ui/webui/pdf_viewer_handler.cc b/atom/browser/ui/webui/pdf_viewer_handler.cc index 699119fb2802..ccebec9931b3 100644 --- a/atom/browser/ui/webui/pdf_viewer_handler.cc +++ b/atom/browser/ui/webui/pdf_viewer_handler.cc @@ -119,7 +119,7 @@ void PdfViewerHandler::Initialize(const base::ListValue* args) { } else { initialize_callback_id_ = callback_id->CreateDeepCopy(); } - + auto zoom_controller = WebContentsZoomController::FromWebContents( web_ui()->GetWebContents()); zoom_controller->SetZoomMode(WebContentsZoomController::ZOOM_MODE_MANUAL); @@ -211,7 +211,7 @@ void PdfViewerHandler::Reload(const base::ListValue* args) { void PdfViewerHandler::OnZoomLevelChanged(content::WebContents* web_contents, double level, bool is_temporary) { if (web_ui()->GetWebContents() == web_contents) { - CallJavascriptFunction("cr.webUIListenerCallback", + CallJavascriptFunction("cr.webUIListenerCallback", base::StringValue("onZoomLevelChanged"), base::Value(content::ZoomLevelToZoomFactor(level))); } diff --git a/atom/browser/ui/webui/pdf_viewer_handler.h b/atom/browser/ui/webui/pdf_viewer_handler.h index 46e7ac8d4edc..e6ae315e8764 100644 --- a/atom/browser/ui/webui/pdf_viewer_handler.h +++ b/atom/browser/ui/webui/pdf_viewer_handler.h @@ -43,7 +43,7 @@ class PdfViewerHandler : public content::WebUIMessageHandler, void SetZoom(const base::ListValue* args); void GetStrings(const base::ListValue* args); void Reload(const base::ListValue* args); - void OnZoomLevelChanged(content::WebContents* web_contents, double level, + void OnZoomLevelChanged(content::WebContents* web_contents, double level, bool is_temporary); std::unique_ptr initialize_callback_id_; diff --git a/atom/browser/web_contents_zoom_controller.cc b/atom/browser/web_contents_zoom_controller.cc index 764fa939784c..3c8d512b6bb4 100644 --- a/atom/browser/web_contents_zoom_controller.cc +++ b/atom/browser/web_contents_zoom_controller.cc @@ -67,7 +67,7 @@ void WebContentsZoomController::SetZoomLevel(double level) { content::HostZoomMap* zoom_map = content::HostZoomMap::GetForWebContents(web_contents()); - if (zoom_mode_ == ZOOM_MODE_ISOLATED || + if (zoom_mode_ == ZOOM_MODE_ISOLATED || zoom_map->UsesTemporaryZoomLevel(render_process_id, render_view_id)) { zoom_map->SetTemporaryZoomLevel( render_process_id, render_view_id, level); @@ -164,7 +164,7 @@ void WebContentsZoomController::SetZoomMode(ZoomMode new_mode) { // When we don't call any HostZoomMap set functions, we send the event // manually. for (Observer& observer : observers_) - observer.OnZoomLevelChanged(web_contents(), original_zoom_level, + observer.OnZoomLevelChanged(web_contents(), original_zoom_level, false); } break; @@ -181,7 +181,7 @@ void WebContentsZoomController::SetZoomMode(ZoomMode new_mode) { // When we don't call any HostZoomMap set functions, we send the event // manually. for (Observer& observer : observers_) - observer.OnZoomLevelChanged(web_contents(), original_zoom_level, + observer.OnZoomLevelChanged(web_contents(), original_zoom_level, false); } break; @@ -211,7 +211,7 @@ void WebContentsZoomController::ResetZoomModeOnNavigationIfNeeded( double new_zoom_level = zoom_map->GetZoomLevelForHostAndScheme( url.scheme(), net::GetHostOrSpecFromURL(url)); for (Observer& observer : observers_) - observer.OnZoomLevelChanged(web_contents(), new_zoom_level, + observer.OnZoomLevelChanged(web_contents(), new_zoom_level, false); zoom_map->ClearTemporaryZoomLevel(render_process_id, render_view_id); zoom_mode_ = ZOOM_MODE_DEFAULT; diff --git a/atom/browser/web_contents_zoom_controller.h b/atom/browser/web_contents_zoom_controller.h index 493219c09410..220d5c45bfad 100644 --- a/atom/browser/web_contents_zoom_controller.h +++ b/atom/browser/web_contents_zoom_controller.h @@ -28,7 +28,7 @@ class WebContentsZoomController protected: virtual ~Observer() {} }; - + // Defines how zoom changes are handled. enum ZoomMode { // Results in default zoom behavior, i.e. zoom changes are handled @@ -67,7 +67,7 @@ class WebContentsZoomController // Sets the zoom mode, which defines zoom behavior (see enum ZoomMode). void SetZoomMode(ZoomMode zoom_mode); - + void ResetZoomModeOnNavigationIfNeeded(const GURL& url); ZoomMode zoom_mode() const { return zoom_mode_; } From a3ec28ddf305a8ea8ee124036d6aae54dc7488bb Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Wed, 14 Jun 2017 00:49:11 +0200 Subject: [PATCH 4/4] remove unused includes --- atom/browser/ui/webui/pdf_viewer_handler.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/atom/browser/ui/webui/pdf_viewer_handler.cc b/atom/browser/ui/webui/pdf_viewer_handler.cc index ccebec9931b3..e00ab9d4d930 100644 --- a/atom/browser/ui/webui/pdf_viewer_handler.cc +++ b/atom/browser/ui/webui/pdf_viewer_handler.cc @@ -8,9 +8,6 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/values.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" #include "content/public/browser/stream_handle.h" #include "content/public/browser/stream_info.h" #include "content/public/browser/web_contents.h"