1 // 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.
5 #ifndef COMPONENTS_UI_ZOOM_ZOOM_CONTROLLER_H_
6 #define COMPONENTS_UI_ZOOM_ZOOM_CONTROLLER_H_
8 #include "base/basictypes.h"
9 #include "base/compiler_specific.h"
10 #include "base/gtest_prod_util.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/observer_list.h"
14 #include "base/prefs/pref_member.h"
15 #include "content/public/browser/host_zoom_map.h"
16 #include "content/public/browser/web_contents_observer.h"
17 #include "content/public/browser/web_contents_user_data.h"
19 class ZoomControllerTest
;
28 class ZoomRequestClient
: public base::RefCounted
<ZoomRequestClient
> {
30 ZoomRequestClient() {}
33 virtual ~ZoomRequestClient() {}
36 friend class base::RefCounted
<ZoomRequestClient
>;
38 DISALLOW_COPY_AND_ASSIGN(ZoomRequestClient
);
41 // Per-tab class to manage zoom changes and the Omnibox zoom icon.
42 class ZoomController
: public content::WebContentsObserver
,
43 public content::WebContentsUserData
<ZoomController
> {
45 // Defines how zoom changes are handled.
47 // Results in default zoom behavior, i.e. zoom changes are handled
48 // automatically and on a per-origin basis, meaning that other tabs
49 // navigated to the same origin will also zoom.
51 // Results in zoom changes being handled automatically, but on a per-tab
52 // basis. Tabs in this zoom mode will not be affected by zoom changes in
53 // other tabs, and vice versa.
55 // Overrides the automatic handling of zoom changes. The |onZoomChange|
56 // event will still be dispatched, but the page will not actually be zoomed.
57 // These zoom changes can be handled manually by listening for the
58 // |onZoomChange| event. Zooming in this mode is also on a per-tab basis.
60 // Disables all zooming in this tab. The tab will revert to the default
61 // zoom level, and all attempted zoom changes will be ignored.
66 ZOOM_BELOW_DEFAULT_ZOOM
,
68 ZOOM_ABOVE_DEFAULT_ZOOM
71 struct ZoomChangedEventData
{
72 ZoomChangedEventData(content::WebContents
* web_contents
,
73 double old_zoom_level
,
74 double new_zoom_level
,
75 ZoomController::ZoomMode zoom_mode
,
77 : web_contents(web_contents
),
78 old_zoom_level(old_zoom_level
),
79 new_zoom_level(new_zoom_level
),
81 can_show_bubble(can_show_bubble
) {}
82 content::WebContents
* web_contents
;
83 double old_zoom_level
;
84 double new_zoom_level
;
85 ZoomController::ZoomMode zoom_mode
;
89 // Since it's possible for a WebContents to not have a ZoomController, provide
90 // a simple, safe and reliable method to find the current zoom level for a
91 // given WebContents*.
92 static double GetZoomLevelForWebContents(
93 const content::WebContents
* web_contents
);
95 ~ZoomController() override
;
97 ZoomMode
zoom_mode() const { return zoom_mode_
; }
99 // Convenience method to get default zoom level. Implemented here for
101 double GetDefaultZoomLevel() const {
102 return content::HostZoomMap::GetForWebContents(web_contents())
103 ->GetDefaultZoomLevel();
106 // Convenience method to quickly check if the tab's at default zoom.
107 bool IsAtDefaultZoom() const;
109 // Returns which image should be loaded for the current zoom level.
110 RelativeZoom
GetZoomRelativeToDefault() const;
112 const ZoomRequestClient
* last_client() const { return last_client_
.get(); }
114 void AddObserver(ZoomObserver
* observer
);
115 void RemoveObserver(ZoomObserver
* observer
);
117 // Used to set whether the zoom notification bubble can be shown when the
118 // zoom level is changed for this controller. Default behavior is to show
120 void SetShowsNotificationBubble(bool can_show_bubble
) {
121 can_show_bubble_
= can_show_bubble
;
124 // Gets the current zoom level by querying HostZoomMap (if not in manual zoom
125 // mode) or from the ZoomController local value otherwise.
126 double GetZoomLevel() const;
127 // Calls GetZoomLevel() then converts the returned value to a percentage
129 // Virtual for testing.
130 virtual int GetZoomPercent() const;
132 // Sets the zoom level through HostZoomMap.
133 // Returns true on success.
134 bool SetZoomLevel(double zoom_level
);
136 // Sets the zoom level via HostZoomMap (or stores it locally if in manual zoom
137 // mode), and attributes the zoom to |client|. Returns true on success.
138 bool SetZoomLevelByClient(
140 const scoped_refptr
<const ZoomRequestClient
>& client
);
142 // Sets the zoom mode, which defines zoom behavior (see enum ZoomMode).
143 void SetZoomMode(ZoomMode zoom_mode
);
145 // Set and query whether or not the page scale factor is one.
146 void SetPageScaleFactorIsOneForTesting(bool is_one
);
147 bool PageScaleFactorIsOne() const;
149 // content::WebContentsObserver overrides:
150 void DidNavigateMainFrame(
151 const content::LoadCommittedDetails
& details
,
152 const content::FrameNavigateParams
& params
) override
;
153 void WebContentsDestroyed() override
;
154 void RenderFrameHostChanged(content::RenderFrameHost
* old_host
,
155 content::RenderFrameHost
* new_host
) override
;
158 // Protected for testing.
159 explicit ZoomController(content::WebContents
* web_contents
);
162 friend class content::WebContentsUserData
<ZoomController
>;
163 friend class ::ZoomControllerTest
;
165 void ResetZoomModeOnNavigationIfNeeded(const GURL
& url
);
166 void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange
& change
);
168 // Updates the zoom icon and zoom percentage based on current values and
169 // notifies the observer if changes have occurred. |host| may be empty,
170 // meaning the change should apply to ~all sites. If it is not empty, the
171 // change only affects sites with the given host.
172 void UpdateState(const std::string
& host
);
174 // True if changes to zoom level can trigger the zoom notification bubble.
175 bool can_show_bubble_
;
177 // The current zoom mode.
180 // Current zoom level.
183 scoped_ptr
<ZoomChangedEventData
> event_data_
;
185 // Keeps track of the extension (if any) that initiated the last zoom change
187 scoped_refptr
<const ZoomRequestClient
> last_client_
;
189 // Observer receiving notifications on state changes.
190 base::ObserverList
<ZoomObserver
> observers_
;
192 content::BrowserContext
* browser_context_
;
193 // Keep track of the HostZoomMap we're currently subscribed to.
194 content::HostZoomMap
* host_zoom_map_
;
196 scoped_ptr
<content::HostZoomMap::Subscription
> zoom_subscription_
;
198 DISALLOW_COPY_AND_ASSIGN(ZoomController
);
201 } // namespace ui_zoom
203 #endif // COMPONENTS_UI_ZOOM_ZOOM_CONTROLLER_H_