15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/zoom/zoom_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/sad_tab.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/ui/zoom/zoom_event_manager.h"
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/browser/ui/zoom/zoom_observer.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/host_zoom_map.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/render_process_host.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/render_view_host.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/page_type.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_zoom.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/extension.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_WEB_CONTENTS_USER_DATA_KEY(ZoomController);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ZoomController::ZoomController(content::WebContents* web_contents)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : content::WebContentsObserver(web_contents),
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      can_show_bubble_(true),
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      zoom_mode_(ZOOM_MODE_DEFAULT),
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      zoom_level_(1.0),
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      browser_context_(web_contents->GetBrowserContext()) {
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(wjmaclean) Make calls to HostZoomMap::GetDefaultForBrowserContext()
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // refer to the webcontents-specific HostZoomMap when that becomes available.
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  content::HostZoomMap* host_zoom_map =
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::HostZoomMap::GetDefaultForBrowserContext(browser_context_);
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  zoom_level_ = host_zoom_map->GetDefaultZoomLevel();
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  zoom_subscription_ = host_zoom_map->AddZoomLevelChangedCallback(
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ZoomController::OnZoomLevelChanged, base::Unretained(this)));
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UpdateState(std::string());
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ZoomController::~ZoomController() {}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ZoomController::IsAtDefaultZoom() const {
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return content::ZoomValuesEqual(GetZoomLevel(), GetDefaultZoomLevel());
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ZoomController::GetResourceForZoomLevel() const {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsAtDefaultZoom())
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return IDR_ZOOM_NORMAL;
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return GetZoomLevel() > GetDefaultZoomLevel() ? IDR_ZOOM_PLUS
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                : IDR_ZOOM_MINUS;
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ZoomController::AddObserver(ZoomObserver* observer) {
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  observers_.AddObserver(observer);
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ZoomController::RemoveObserver(ZoomObserver* observer) {
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  observers_.RemoveObserver(observer);
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdochdouble ZoomController::GetZoomLevel() const {
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return zoom_mode_ == ZOOM_MODE_MANUAL ?
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch             zoom_level_:
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch             content::HostZoomMap::GetZoomLevel(web_contents());
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint ZoomController::GetZoomPercent() const {
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  double zoom_factor = content::ZoomLevelToZoomFactor(GetZoomLevel());
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Round double for return.
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return static_cast<int>(zoom_factor * 100 + 0.5);
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ZoomController::SetZoomLevel(double zoom_level) {
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // An extension did not initiate this zoom change.
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return SetZoomLevelByExtension(zoom_level, NULL);
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool ZoomController::SetZoomLevelByExtension(
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    double zoom_level,
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const scoped_refptr<const extensions::Extension>& extension) {
8234680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  content::NavigationEntry* entry =
8334680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      web_contents()->GetController().GetLastCommittedEntry();
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool is_normal_page =
8534680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)      entry && entry->GetPageType() == content::PAGE_TYPE_NORMAL;
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Cannot zoom in disabled mode. Also, don't allow changing zoom level on
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // a crashed tab, an error page or an interstitial page.
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (zoom_mode_ == ZOOM_MODE_DISABLED ||
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !web_contents()->GetRenderViewHost()->IsRenderViewLive() ||
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !is_normal_page)
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Store extension data so that |extension| can be attributed when the zoom
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // change completes. We expect that by the time this function returns that
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // any observers that require this information will have requested it.
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  last_extension_ = extension;
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Do not actually rescale the page in manual mode.
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (zoom_mode_ == ZOOM_MODE_MANUAL) {
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    double old_zoom_level = zoom_level_;
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    zoom_level_ = zoom_level;
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO(wjmaclean) Do we care about filling in host/scheme here?
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::HostZoomMap::ZoomLevelChange change;
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    change.mode = content::HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM;
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    change.zoom_level = zoom_level;
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ZoomEventManager::GetForBrowserContext(browser_context_)->
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        OnZoomLevelChanged(change);
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ZoomChangedEventData zoom_change_data(web_contents(),
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          old_zoom_level,
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          zoom_level_,
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          zoom_mode_,
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          false /* can_show_bubble */);
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FOR_EACH_OBSERVER(
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ZoomObserver, observers_, OnZoomChanged(zoom_change_data));
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    last_extension_ = NULL;
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return true;
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  content::HostZoomMap* zoom_map =
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::HostZoomMap::GetDefaultForBrowserContext(browser_context_);
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(zoom_map);
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!event_data_);
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  event_data_.reset(new ZoomChangedEventData(web_contents(),
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             GetZoomLevel(),
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             zoom_level,
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             zoom_mode_,
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             false /* can_show_bubble */));
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (zoom_mode_ == ZOOM_MODE_ISOLATED ||
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      zoom_map->UsesTemporaryZoomLevel(render_process_id, render_view_id)) {
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    zoom_map->SetTemporaryZoomLevel(
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        render_process_id, render_view_id, zoom_level);
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!entry) {
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      last_extension_ = NULL;
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    std::string host = net::GetHostOrSpecFromURL(entry->GetURL());
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    zoom_map->SetZoomLevelForHost(host, zoom_level);
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!event_data_);
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  last_extension_ = NULL;
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ZoomController::SetZoomMode(ZoomMode new_mode) {
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (new_mode == zoom_mode_)
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  content::HostZoomMap* zoom_map =
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::HostZoomMap::GetDefaultForBrowserContext(browser_context_);
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(zoom_map);
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int render_process_id = web_contents()->GetRenderProcessHost()->GetID();
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int render_view_id = web_contents()->GetRenderViewHost()->GetRoutingID();
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  double original_zoom_level = GetZoomLevel();
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!event_data_);
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  event_data_.reset(new ZoomChangedEventData(web_contents(),
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             original_zoom_level,
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             original_zoom_level,
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             new_mode,
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             new_mode != ZOOM_MODE_DEFAULT));
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  switch (new_mode) {
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case ZOOM_MODE_DEFAULT: {
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      content::NavigationEntry* entry =
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          web_contents()->GetController().GetLastCommittedEntry();
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (entry) {
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        GURL url = entry->GetURL();
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        std::string host = net::GetHostOrSpecFromURL(url);
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        if (zoom_map->HasZoomLevel(url.scheme(), host)) {
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // If there are other tabs with the same origin, then set this tab's
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // zoom level to match theirs. The temporary zoom level will be
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // cleared below, but this call will make sure this tab re-draws at
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // the correct zoom level.
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          double origin_zoom_level =
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              zoom_map->GetZoomLevelForHostAndScheme(url.scheme(), host);
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          event_data_->new_zoom_level = origin_zoom_level;
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          zoom_map->SetTemporaryZoomLevel(
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              render_process_id, render_view_id, origin_zoom_level);
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        } else {
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // The host will need a level prior to removing the temporary level.
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // We don't want the zoom level to change just because we entered
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          // default mode.
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          zoom_map->SetZoomLevelForHost(host, original_zoom_level);
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        }
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Remove per-tab zoom data for this tab. No event callback expected.
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      zoom_map->ClearTemporaryZoomLevel(render_process_id, render_view_id);
197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case ZOOM_MODE_ISOLATED: {
200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // page needs an initial isolated zoom back to the same level it was at
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // in the other mode.
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (zoom_mode_ != ZOOM_MODE_DISABLED) {
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        zoom_map->SetTemporaryZoomLevel(
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            render_process_id, render_view_id, original_zoom_level);
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      } else {
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // When we don't call any HostZoomMap set functions, we send the event
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // manually.
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        FOR_EACH_OBSERVER(
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            ZoomObserver, observers_, OnZoomChanged(*event_data_));
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        event_data_.reset();
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case ZOOM_MODE_MANUAL: {
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Unless the zoom mode was |ZOOM_MODE_DISABLED| before this call, the
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // page needs to be resized to the default zoom. While in manual mode,
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // the zoom level is handled independently.
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (zoom_mode_ != ZOOM_MODE_DISABLED) {
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        zoom_map->SetTemporaryZoomLevel(
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            render_process_id, render_view_id, GetDefaultZoomLevel());
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        zoom_level_ = original_zoom_level;
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      } else {
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // When we don't call any HostZoomMap set functions, we send the event
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        // manually.
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        FOR_EACH_OBSERVER(
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            ZoomObserver, observers_, OnZoomChanged(*event_data_));
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        event_data_.reset();
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case ZOOM_MODE_DISABLED: {
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // The page needs to be zoomed back to default before disabling the zoom
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      zoom_map->SetTemporaryZoomLevel(
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          render_process_id, render_view_id, GetDefaultZoomLevel());
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Any event data we've stored should have been consumed by this point.
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!event_data_);
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  zoom_mode_ = new_mode;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ZoomController::DidNavigateMainFrame(
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::LoadCommittedDetails& details,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::FrameNavigateParams& params) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the main frame's content has changed, the new page may have a different
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // zoom level from the old one.
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UpdateState(std::string());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ZoomController::WebContentsDestroyed() {
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // At this point we should no longer be sending any zoom events with this
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // WebContents.
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  observers_.Clear();
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ZoomController::OnZoomLevelChanged(
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::HostZoomMap::ZoomLevelChange& change) {
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  UpdateState(change.host);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ZoomController::UpdateState(const std::string& host) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If |host| is empty, all observers should be updated.
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!host.empty()) {
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Use the navigation entry's URL instead of the WebContents' so virtual
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // URLs work (e.g. chrome://settings). http://crbug.com/153950
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::NavigationEntry* entry =
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        web_contents()->GetController().GetLastCommittedEntry();
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!entry ||
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        host != net::GetHostOrSpecFromURL(entry->GetURL())) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The zoom bubble should not be shown for zoom changes where the host is
278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // empty.
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool can_show_bubble = can_show_bubble_ && !host.empty();
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (event_data_) {
282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // For state changes initiated within the ZoomController, information about
283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // the change should be sent.
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ZoomChangedEventData zoom_change_data = *event_data_;
285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    event_data_.reset();
286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    zoom_change_data.can_show_bubble = can_show_bubble;
287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FOR_EACH_OBSERVER(
288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ZoomObserver, observers_, OnZoomChanged(zoom_change_data));
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO(wjmaclean) Should we consider having HostZoomMap send both old and
291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // new zoom levels here?
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    double zoom_level = GetZoomLevel();
293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ZoomChangedEventData zoom_change_data(
294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        web_contents(), zoom_level, zoom_level, zoom_mode_, can_show_bubble);
295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    FOR_EACH_OBSERVER(
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ZoomObserver, observers_, OnZoomChanged(zoom_change_data));
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
299