Home | History | Annotate | Download | only in zoom
      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.
      4 
      5 #ifndef CHROME_BROWSER_UI_ZOOM_ZOOM_CONTROLLER_H_
      6 #define CHROME_BROWSER_UI_ZOOM_ZOOM_CONTROLLER_H_
      7 
      8 #include "base/basictypes.h"
      9 #include "base/compiler_specific.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/observer_list.h"
     12 #include "base/prefs/pref_member.h"
     13 #include "content/public/browser/host_zoom_map.h"
     14 #include "content/public/browser/web_contents_observer.h"
     15 #include "content/public/browser/web_contents_user_data.h"
     16 
     17 class ZoomObserver;
     18 
     19 namespace content {
     20 class WebContents;
     21 }
     22 
     23 namespace extensions {
     24 class Extension;
     25 }  // namespace extensions
     26 
     27 // Per-tab class to manage zoom changes and the Omnibox zoom icon.
     28 class ZoomController : public content::WebContentsObserver,
     29                        public content::WebContentsUserData<ZoomController> {
     30  public:
     31   // Defines how zoom changes are handled.
     32   enum ZoomMode {
     33     // Results in default zoom behavior, i.e. zoom changes are handled
     34     // automatically and on a per-origin basis, meaning that other tabs
     35     // navigated to the same origin will also zoom.
     36     ZOOM_MODE_DEFAULT,
     37     // Results in zoom changes being handled automatically, but on a per-tab
     38     // basis. Tabs in this zoom mode will not be affected by zoom changes in
     39     // other tabs, and vice versa.
     40     ZOOM_MODE_ISOLATED,
     41     // Overrides the automatic handling of zoom changes. The |onZoomChange|
     42     // event will still be dispatched, but the page will not actually be zoomed.
     43     // These zoom changes can be handled manually by listening for the
     44     // |onZoomChange| event. Zooming in this mode is also on a per-tab basis.
     45     ZOOM_MODE_MANUAL,
     46     // Disables all zooming in this tab. The tab will revert to default (100%)
     47     // zoom, and all attempted zoom changes will be ignored.
     48     ZOOM_MODE_DISABLED,
     49   };
     50 
     51   struct ZoomChangedEventData {
     52     ZoomChangedEventData(content::WebContents* web_contents,
     53                          double old_zoom_level,
     54                          double new_zoom_level,
     55                          ZoomController::ZoomMode zoom_mode,
     56                          bool can_show_bubble)
     57         : web_contents(web_contents),
     58           old_zoom_level(old_zoom_level),
     59           new_zoom_level(new_zoom_level),
     60           zoom_mode(zoom_mode),
     61           can_show_bubble(can_show_bubble) {}
     62     content::WebContents* web_contents;
     63     double old_zoom_level;
     64     double new_zoom_level;
     65     ZoomController::ZoomMode zoom_mode;
     66     bool can_show_bubble;
     67   };
     68 
     69   virtual ~ZoomController();
     70 
     71   ZoomMode zoom_mode() const { return zoom_mode_; }
     72 
     73   // Convenience method to get default zoom level. Implemented here for
     74   // inlining.
     75   double GetDefaultZoomLevel() const {
     76     // TODO(wjmaclean) Make this refer to the webcontents-specific HostZoomMap
     77     // when that becomes available.
     78     return content::HostZoomMap::GetDefaultForBrowserContext(browser_context_)->
     79         GetDefaultZoomLevel();
     80   }
     81 
     82   // Convenience method to quickly check if the tab's at default zoom.
     83   bool IsAtDefaultZoom() const;
     84 
     85   // Returns which image should be loaded for the current zoom level.
     86   int GetResourceForZoomLevel() const;
     87 
     88   const extensions::Extension* last_extension() const {
     89     return last_extension_.get();
     90   }
     91 
     92   void AddObserver(ZoomObserver* observer);
     93   void RemoveObserver(ZoomObserver* observer);
     94 
     95   // Used to set whether the zoom notification bubble can be shown when the
     96   // zoom level is changed for this controller. Default behavior is to show
     97   // the bubble.
     98   void SetShowsNotificationBubble(bool can_show_bubble) {
     99     can_show_bubble_ = can_show_bubble;
    100   }
    101 
    102   // Gets the current zoom level by querying HostZoomMap (if not in manual zoom
    103   // mode) or from the ZoomController local value otherwise.
    104   double GetZoomLevel() const;
    105   // Calls GetZoomLevel() then converts the returned value to a percentage
    106   // zoom factor.
    107   // Virtual for testing.
    108   virtual int GetZoomPercent() const;
    109 
    110   // Sets the zoom level through HostZoomMap.
    111   // Returns true on success.
    112   bool SetZoomLevel(double zoom_level);
    113 
    114   // Sets the zoom level via HostZoomMap (or stores it locally if in manual zoom
    115   // mode), and attributes the zoom to |extension|. Returns true on success.
    116   bool SetZoomLevelByExtension(
    117       double zoom_level,
    118       const scoped_refptr<const extensions::Extension>& extension);
    119 
    120   // Sets the zoom mode, which defines zoom behavior (see enum ZoomMode).
    121   void SetZoomMode(ZoomMode zoom_mode);
    122 
    123   // content::WebContentsObserver overrides:
    124   virtual void DidNavigateMainFrame(
    125       const content::LoadCommittedDetails& details,
    126       const content::FrameNavigateParams& params) OVERRIDE;
    127   virtual void WebContentsDestroyed() OVERRIDE;
    128 
    129  protected:
    130   // Protected for testing.
    131   explicit ZoomController(content::WebContents* web_contents);
    132 
    133  private:
    134   friend class content::WebContentsUserData<ZoomController>;
    135   friend class ZoomControllerTest;
    136 
    137   void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change);
    138 
    139   // Updates the zoom icon and zoom percentage based on current values and
    140   // notifies the observer if changes have occurred. |host| may be empty,
    141   // meaning the change should apply to ~all sites. If it is not empty, the
    142   // change only affects sites with the given host.
    143   void UpdateState(const std::string& host);
    144 
    145   // True if changes to zoom level can trigger the zoom notification bubble.
    146   bool can_show_bubble_;
    147 
    148   // The current zoom mode.
    149   ZoomMode zoom_mode_;
    150 
    151   // Current zoom level.
    152   double zoom_level_;
    153 
    154   scoped_ptr<ZoomChangedEventData> event_data_;
    155 
    156   // Keeps track of the extension (if any) that initiated the last zoom change
    157   // that took effect.
    158   scoped_refptr<const extensions::Extension> last_extension_;
    159 
    160   // Observer receiving notifications on state changes.
    161   ObserverList<ZoomObserver> observers_;
    162 
    163   content::BrowserContext* browser_context_;
    164 
    165   scoped_ptr<content::HostZoomMap::Subscription> zoom_subscription_;
    166 
    167   DISALLOW_COPY_AND_ASSIGN(ZoomController);
    168 };
    169 
    170 #endif  // CHROME_BROWSER_UI_ZOOM_ZOOM_CONTROLLER_H_
    171