blob: 5ce1ce154156cdc0f4c8c7b1e9b20b65c9d67198 [file] [log] [blame]
[email protected]6f80e932012-06-04 19:00:071// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
juncaia64f769c22016-06-04 00:55:325#ifndef COMPONENTS_ZOOM_ZOOM_CONTROLLER_H_
6#define COMPONENTS_ZOOM_ZOOM_CONTROLLER_H_
[email protected]6f80e932012-06-04 19:00:077
dcheng3f767dc32016-04-25 22:54:228#include <memory>
9
[email protected]6f80e932012-06-04 19:00:0710#include "base/compiler_specific.h"
avi5dd91f82015-12-25 22:30:4611#include "base/macros.h"
wjmaclean7f63c6b2014-12-09 14:59:5512#include "base/memory/ref_counted.h"
[email protected]63d1f9b2014-07-05 19:09:0313#include "base/observer_list.h"
brettwf00b9b42016-02-01 22:11:3814#include "components/prefs/pref_member.h"
[email protected]89c9aca2013-02-07 15:08:4215#include "content/public/browser/host_zoom_map.h"
[email protected]6f80e932012-06-04 19:00:0716#include "content/public/browser/web_contents_observer.h"
[email protected]46b3c982012-10-09 18:38:3017#include "content/public/browser/web_contents_user_data.h"
[email protected]6f80e932012-06-04 19:00:0718
wjmaclean7f63c6b2014-12-09 14:59:5519class ZoomControllerTest;
[email protected]ff3d94e2012-12-18 07:16:3120
[email protected]dea9cee82012-09-25 03:10:5221namespace content {
22class WebContents;
23}
24
juncaia64f769c22016-06-04 00:55:3225namespace zoom {
wjmaclean7f63c6b2014-12-09 14:59:5526class ZoomObserver;
27
28class ZoomRequestClient : public base::RefCounted<ZoomRequestClient> {
29 public:
30 ZoomRequestClient() {}
wjmaclean70eb6d832015-10-29 21:10:0931 virtual bool ShouldSuppressBubble() const = 0;
wjmaclean7f63c6b2014-12-09 14:59:5532
33 protected:
34 virtual ~ZoomRequestClient() {}
35
36 private:
37 friend class base::RefCounted<ZoomRequestClient>;
38
39 DISALLOW_COPY_AND_ASSIGN(ZoomRequestClient);
40};
[email protected]63d1f9b2014-07-05 19:09:0341
Lei Zhang9d40e7902017-11-20 19:54:3642// Per-tab class to manage zoom changes and the Omnibox zoom icon. Lives on the
43// UI thread.
[email protected]89c9aca2013-02-07 15:08:4244class ZoomController : public content::WebContentsObserver,
[email protected]46b3c982012-10-09 18:38:3045 public content::WebContentsUserData<ZoomController> {
[email protected]6f80e932012-06-04 19:00:0746 public:
[email protected]63d1f9b2014-07-05 19:09:0347 // Defines how zoom changes are handled.
48 enum ZoomMode {
49 // Results in default zoom behavior, i.e. zoom changes are handled
50 // automatically and on a per-origin basis, meaning that other tabs
51 // navigated to the same origin will also zoom.
52 ZOOM_MODE_DEFAULT,
53 // Results in zoom changes being handled automatically, but on a per-tab
54 // basis. Tabs in this zoom mode will not be affected by zoom changes in
55 // other tabs, and vice versa.
56 ZOOM_MODE_ISOLATED,
57 // Overrides the automatic handling of zoom changes. The |onZoomChange|
58 // event will still be dispatched, but the page will not actually be zoomed.
59 // These zoom changes can be handled manually by listening for the
60 // |onZoomChange| event. Zooming in this mode is also on a per-tab basis.
61 ZOOM_MODE_MANUAL,
paulmeyer65703af2015-04-01 19:33:4862 // Disables all zooming in this tab. The tab will revert to the default
63 // zoom level, and all attempted zoom changes will be ignored.
[email protected]63d1f9b2014-07-05 19:09:0364 ZOOM_MODE_DISABLED,
65 };
66
wjmaclean7f63c6b2014-12-09 14:59:5567 enum RelativeZoom {
68 ZOOM_BELOW_DEFAULT_ZOOM,
69 ZOOM_AT_DEFAULT_ZOOM,
70 ZOOM_ABOVE_DEFAULT_ZOOM
71 };
72
[email protected]63d1f9b2014-07-05 19:09:0373 struct ZoomChangedEventData {
74 ZoomChangedEventData(content::WebContents* web_contents,
75 double old_zoom_level,
76 double new_zoom_level,
77 ZoomController::ZoomMode zoom_mode,
78 bool can_show_bubble)
79 : web_contents(web_contents),
80 old_zoom_level(old_zoom_level),
81 new_zoom_level(new_zoom_level),
82 zoom_mode(zoom_mode),
83 can_show_bubble(can_show_bubble) {}
84 content::WebContents* web_contents;
85 double old_zoom_level;
86 double new_zoom_level;
87 ZoomController::ZoomMode zoom_mode;
88 bool can_show_bubble;
89 };
90
wjmacleanbd731172015-03-31 16:07:5991 // Since it's possible for a WebContents to not have a ZoomController, provide
92 // a simple, safe and reliable method to find the current zoom level for a
93 // given WebContents*.
Lucas Furukawa Gadanie1c5dfda2018-11-29 17:57:4194 static double GetZoomLevelForWebContents(content::WebContents* web_contents);
wjmacleanbd731172015-03-31 16:07:5995
dcheng5dd5ff62014-10-21 12:42:3896 ~ZoomController() override;
[email protected]6f80e932012-06-04 19:00:0797
[email protected]63d1f9b2014-07-05 19:09:0398 ZoomMode zoom_mode() const { return zoom_mode_; }
[email protected]6f80e932012-06-04 19:00:0799
wjmaclean32a991c2014-09-02 14:13:47100 // Convenience method to get default zoom level. Implemented here for
101 // inlining.
102 double GetDefaultZoomLevel() const {
wjmacleancaa7d6d2014-11-12 16:42:11103 return content::HostZoomMap::GetForWebContents(web_contents())
104 ->GetDefaultZoomLevel();
wjmaclean32a991c2014-09-02 14:13:47105 }
106
[email protected]5423c372012-08-22 05:50:16107 // Convenience method to quickly check if the tab's at default zoom.
shrikec12fa88b2016-10-14 18:21:59108 // Virtual for testing.
109 virtual bool IsAtDefaultZoom() const;
[email protected]5423c372012-08-22 05:50:16110
111 // Returns which image should be loaded for the current zoom level.
wjmaclean7f63c6b2014-12-09 14:59:55112 RelativeZoom GetZoomRelativeToDefault() const;
[email protected]5423c372012-08-22 05:50:16113
wjmaclean7f63c6b2014-12-09 14:59:55114 const ZoomRequestClient* last_client() const { return last_client_.get(); }
[email protected]63d1f9b2014-07-05 19:09:03115
116 void AddObserver(ZoomObserver* observer);
117 void RemoveObserver(ZoomObserver* observer);
118
[email protected]d27c65262014-07-10 02:51:54119 // Used to set whether the zoom notification bubble can be shown when the
120 // zoom level is changed for this controller. Default behavior is to show
121 // the bubble.
122 void SetShowsNotificationBubble(bool can_show_bubble) {
123 can_show_bubble_ = can_show_bubble;
124 }
125
[email protected]63d1f9b2014-07-05 19:09:03126 // Gets the current zoom level by querying HostZoomMap (if not in manual zoom
127 // mode) or from the ZoomController local value otherwise.
128 double GetZoomLevel() const;
129 // Calls GetZoomLevel() then converts the returned value to a percentage
130 // zoom factor.
[email protected]212676782014-08-11 17:50:18131 // Virtual for testing.
132 virtual int GetZoomPercent() const;
[email protected]63d1f9b2014-07-05 19:09:03133
134 // Sets the zoom level through HostZoomMap.
135 // Returns true on success.
136 bool SetZoomLevel(double zoom_level);
137
138 // Sets the zoom level via HostZoomMap (or stores it locally if in manual zoom
wjmaclean7f63c6b2014-12-09 14:59:55139 // mode), and attributes the zoom to |client|. Returns true on success.
140 bool SetZoomLevelByClient(
[email protected]63d1f9b2014-07-05 19:09:03141 double zoom_level,
wjmaclean7f63c6b2014-12-09 14:59:55142 const scoped_refptr<const ZoomRequestClient>& client);
[email protected]63d1f9b2014-07-05 19:09:03143
144 // Sets the zoom mode, which defines zoom behavior (see enum ZoomMode).
145 void SetZoomMode(ZoomMode zoom_mode);
[email protected]6f80e932012-06-04 19:00:07146
ccameronb7c1d6c2015-03-09 17:08:24147 // Set and query whether or not the page scale factor is one.
148 void SetPageScaleFactorIsOneForTesting(bool is_one);
149 bool PageScaleFactorIsOne() const;
150
[email protected]6f80e932012-06-04 19:00:07151 // content::WebContentsObserver overrides:
jame1f39842017-01-27 23:14:18152 void DidFinishNavigation(
153 content::NavigationHandle* navigation_handle) override;
dcheng5dd5ff62014-10-21 12:42:38154 void WebContentsDestroyed() override;
wjmacleanc7bcb77d2014-12-16 15:05:38155 void RenderFrameHostChanged(content::RenderFrameHost* old_host,
156 content::RenderFrameHost* new_host) override;
[email protected]6f80e932012-06-04 19:00:07157
[email protected]212676782014-08-11 17:50:18158 protected:
159 // Protected for testing.
[email protected]550fd3772012-11-20 01:06:02160 explicit ZoomController(content::WebContents* web_contents);
[email protected]212676782014-08-11 17:50:18161
162 private:
[email protected]550fd3772012-11-20 01:06:02163 friend class content::WebContentsUserData<ZoomController>;
wjmaclean7f63c6b2014-12-09 14:59:55164 friend class ::ZoomControllerTest;
[email protected]550fd3772012-11-20 01:06:02165
wjmacleand96f8642015-01-07 20:10:57166 void ResetZoomModeOnNavigationIfNeeded(const GURL& url);
[email protected]367c5c1d2013-03-11 18:59:02167 void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change);
[email protected]89c9aca2013-02-07 15:08:42168
[email protected]6f80e932012-06-04 19:00:07169 // Updates the zoom icon and zoom percentage based on current values and
[email protected]9a8408902012-09-26 16:17:59170 // notifies the observer if changes have occurred. |host| may be empty,
171 // meaning the change should apply to ~all sites. If it is not empty, the
[email protected]4ff2b5e2013-07-13 03:39:54172 // change only affects sites with the given host.
173 void UpdateState(const std::string& host);
[email protected]6f80e932012-06-04 19:00:07174
[email protected]d27c65262014-07-10 02:51:54175 // True if changes to zoom level can trigger the zoom notification bubble.
176 bool can_show_bubble_;
177
[email protected]63d1f9b2014-07-05 19:09:03178 // The current zoom mode.
179 ZoomMode zoom_mode_;
180
181 // Current zoom level.
182 double zoom_level_;
[email protected]6f80e932012-06-04 19:00:07183
dcheng3f767dc32016-04-25 22:54:22184 std::unique_ptr<ZoomChangedEventData> event_data_;
[email protected]63d1f9b2014-07-05 19:09:03185
186 // Keeps track of the extension (if any) that initiated the last zoom change
187 // that took effect.
wjmaclean7f63c6b2014-12-09 14:59:55188 scoped_refptr<const ZoomRequestClient> last_client_;
[email protected]63d1f9b2014-07-05 19:09:03189
[email protected]6f80e932012-06-04 19:00:07190 // Observer receiving notifications on state changes.
Trent Apteda250ec3ab2018-08-19 08:52:19191 base::ObserverList<ZoomObserver>::Unchecked observers_;
[email protected]6f80e932012-06-04 19:00:07192
[email protected]89c9aca2013-02-07 15:08:42193 content::BrowserContext* browser_context_;
wjmacleanc7bcb77d2014-12-16 15:05:38194 // Keep track of the HostZoomMap we're currently subscribed to.
195 content::HostZoomMap* host_zoom_map_;
[email protected]89c9aca2013-02-07 15:08:42196
Peter Kasting7ba9440c2020-11-22 01:49:02197 base::CallbackListSubscription zoom_subscription_;
[email protected]89c9aca2013-02-07 15:08:42198
François Doray4f51d5d2018-12-03 22:26:24199 WEB_CONTENTS_USER_DATA_KEY_DECL();
200
[email protected]6f80e932012-06-04 19:00:07201 DISALLOW_COPY_AND_ASSIGN(ZoomController);
202};
203
juncaia64f769c22016-06-04 00:55:32204} // namespace zoom
wjmaclean7f63c6b2014-12-09 14:59:55205
juncaia64f769c22016-06-04 00:55:32206#endif // COMPONENTS_ZOOM_ZOOM_CONTROLLER_H_