Zoom Extension API (content changes)

Changes to content/ needed to facilitate the new zoom extension API,
which is outlined in:

https://docs.google.com/a/chromium.org/document/d/1sCZjx1J3_M2a02T8NXd-ufGKZDoBHI5Ixis1DaGLQCA/edit?usp=sharing

Based on code from https://codereview.chromium.org/226523006/, with
various fixes and rebased against changes in
https://codereview.chromium.org/287093002/

Must land before https://codereview.chromium.org/301733006/.

BUG=30583

Review URL: https://codereview.chromium.org/302603012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277153 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/host_zoom_map_impl.cc b/content/browser/host_zoom_map_impl.cc
index c52d54f8..1b5f7a2f 100644
--- a/content/browser/host_zoom_map_impl.cc
+++ b/content/browser/host_zoom_map_impl.cc
@@ -27,6 +27,27 @@
 
 namespace content {
 
+namespace {
+
+std::string GetHostFromProcessView(int render_process_id, int render_view_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  RenderViewHost* render_view_host =
+      RenderViewHost::FromID(render_process_id, render_view_id);
+  if (!render_view_host)
+    return std::string();
+
+  WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
+
+  NavigationEntry* entry =
+      web_contents->GetController().GetLastCommittedEntry();
+  if (!entry)
+    return std::string();
+
+  return net::GetHostOrSpecFromURL(entry->GetURL());
+}
+
+}  // namespace
+
 HostZoomMap* HostZoomMap::GetForBrowserContext(BrowserContext* context) {
   HostZoomMapImpl* rv = static_cast<HostZoomMapImpl*>(
       context->GetUserData(kHostZoomMapKeyName));
@@ -87,6 +108,22 @@
   return (i == host_zoom_levels_.end()) ? default_zoom_level_ : i->second;
 }
 
+bool HostZoomMapImpl::HasZoomLevel(const std::string& scheme,
+                                   const std::string& host) const {
+  base::AutoLock auto_lock(lock_);
+
+  SchemeHostZoomLevels::const_iterator scheme_iterator(
+      scheme_host_zoom_levels_.find(scheme));
+
+  const HostZoomLevels& zoom_levels =
+      (scheme_iterator != scheme_host_zoom_levels_.end())
+          ? scheme_iterator->second
+          : host_zoom_levels_;
+
+  HostZoomLevels::const_iterator i(zoom_levels.find(host));
+  return i != zoom_levels.end();
+}
+
 double HostZoomMapImpl::GetZoomLevelForHostAndScheme(
     const std::string& scheme,
     const std::string& host) const {
@@ -152,16 +189,9 @@
       host_zoom_levels_[host] = level;
   }
 
-  // Notify renderers from this browser context.
-  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
-       !i.IsAtEnd(); i.Advance()) {
-    RenderProcessHost* render_process_host = i.GetCurrentValue();
-    if (HostZoomMap::GetForBrowserContext(
-            render_process_host->GetBrowserContext()) == this) {
-      render_process_host->Send(
-          new ViewMsg_SetZoomLevelForCurrentURL(std::string(), host, level));
-    }
-  }
+  // TODO(wjmaclean) Should we use a GURL here? crbug.com/384486
+  SendZoomLevelChange(std::string(), host, level);
+
   HostZoomMap::ZoomLevelChange change;
   change.mode = HostZoomMap::ZOOM_CHANGED_FOR_HOST;
   change.host = host;
@@ -179,16 +209,7 @@
     scheme_host_zoom_levels_[scheme][host] = level;
   }
 
-  // Notify renderers from this browser context.
-  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
-       !i.IsAtEnd(); i.Advance()) {
-    RenderProcessHost* render_process_host = i.GetCurrentValue();
-    if (HostZoomMap::GetForBrowserContext(
-            render_process_host->GetBrowserContext()) == this) {
-      render_process_host->Send(
-          new ViewMsg_SetZoomLevelForCurrentURL(scheme, host, level));
-    }
-  }
+  SendZoomLevelChange(scheme, host, level);
 
   HostZoomMap::ZoomLevelChange change;
   change.mode = HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST;
@@ -271,45 +292,20 @@
 
 bool HostZoomMapImpl::UsesTemporaryZoomLevel(int render_process_id,
                                              int render_view_id) const {
-  TemporaryZoomLevel zoom_level(render_process_id, render_view_id);
+  RenderViewKey key(render_process_id, render_view_id);
 
   base::AutoLock auto_lock(lock_);
-  TemporaryZoomLevels::const_iterator it = std::find(
-      temporary_zoom_levels_.begin(), temporary_zoom_levels_.end(), zoom_level);
-  return it != temporary_zoom_levels_.end();
-}
-
-void HostZoomMapImpl::SetUsesTemporaryZoomLevel(
-    int render_process_id,
-    int render_view_id,
-    bool uses_temporary_zoom_level) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  TemporaryZoomLevel zoom_level(
-      render_process_id, render_view_id, default_zoom_level_);
-
-  base::AutoLock auto_lock(lock_);
-  TemporaryZoomLevels::iterator it = std::find(
-      temporary_zoom_levels_.begin(), temporary_zoom_levels_.end(), zoom_level);
-  if (uses_temporary_zoom_level) {
-    if (it == temporary_zoom_levels_.end())
-      temporary_zoom_levels_.push_back(zoom_level);
-  } else if (it != temporary_zoom_levels_.end()) {
-      temporary_zoom_levels_.erase(it);
-  }
+  return ContainsKey(temporary_zoom_levels_, key);
 }
 
 double HostZoomMapImpl::GetTemporaryZoomLevel(int render_process_id,
                                               int render_view_id) const {
   base::AutoLock auto_lock(lock_);
-  for (size_t i = 0; i < temporary_zoom_levels_.size(); ++i) {
-    if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
-        temporary_zoom_levels_[i].render_view_id == render_view_id) {
-      return temporary_zoom_levels_[i].zoom_level;
-    }
-  }
+  RenderViewKey key(render_process_id, render_view_id);
+  if (!ContainsKey(temporary_zoom_levels_, key))
+    return 0;
 
-  return 0;
+  return temporary_zoom_levels_.find(key)->second;
 }
 
 void HostZoomMapImpl::SetTemporaryZoomLevel(int render_process_id,
@@ -318,28 +314,18 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   {
+    RenderViewKey key(render_process_id, render_view_id);
     base::AutoLock auto_lock(lock_);
-    size_t i;
-    for (i = 0; i < temporary_zoom_levels_.size(); ++i) {
-      if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
-          temporary_zoom_levels_[i].render_view_id == render_view_id) {
-        if (level) {
-          temporary_zoom_levels_[i].zoom_level = level;
-        } else {
-          temporary_zoom_levels_.erase(temporary_zoom_levels_.begin() + i);
-        }
-        break;
-      }
-    }
-
-    if (level && i == temporary_zoom_levels_.size()) {
-      TemporaryZoomLevel temp(render_process_id, render_view_id, level);
-      temporary_zoom_levels_.push_back(temp);
-    }
+    temporary_zoom_levels_[key] = level;
   }
 
+  RenderViewHost* host =
+      RenderViewHost::FromID(render_process_id, render_view_id);
+  host->Send(new ViewMsg_SetZoomLevelForView(render_view_id, true, level));
+
   HostZoomMap::ZoomLevelChange change;
   change.mode = HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM;
+  change.host = GetHostFromProcessView(render_process_id, render_view_id);
   change.zoom_level = level;
 
   zoom_level_changed_callbacks_.Notify(change);
@@ -350,18 +336,10 @@
                               const NotificationDetails& details) {
   switch (type) {
     case NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW: {
-      base::AutoLock auto_lock(lock_);
       int render_view_id = Source<RenderViewHost>(source)->GetRoutingID();
       int render_process_id =
           Source<RenderViewHost>(source)->GetProcess()->GetID();
-
-      for (size_t i = 0; i < temporary_zoom_levels_.size(); ++i) {
-        if (temporary_zoom_levels_[i].render_process_id == render_process_id &&
-            temporary_zoom_levels_[i].render_view_id == render_view_id) {
-          temporary_zoom_levels_.erase(temporary_zoom_levels_.begin() + i);
-          break;
-        }
-      }
+      ClearTemporaryZoomLevel(render_process_id, render_view_id);
       break;
     }
     default:
@@ -369,28 +347,42 @@
   }
 }
 
+void HostZoomMapImpl::ClearTemporaryZoomLevel(int render_process_id,
+                                              int render_view_id) {
+  {
+    base::AutoLock auto_lock(lock_);
+    RenderViewKey key(render_process_id, render_view_id);
+    TemporaryZoomLevels::iterator it = temporary_zoom_levels_.find(key);
+    if (it == temporary_zoom_levels_.end())
+      return;
+    temporary_zoom_levels_.erase(it);
+  }
+  RenderViewHost* host =
+      RenderViewHost::FromID(render_process_id, render_view_id);
+  DCHECK(host);
+  // Send a new zoom level, host-specific if one exists.
+  host->Send(new ViewMsg_SetZoomLevelForView(
+      render_view_id,
+      false,
+      GetZoomLevelForHost(
+          GetHostFromProcessView(render_process_id, render_view_id))));
+}
+
+void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme,
+                                          const std::string& host,
+                                          double level) {
+  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
+       !i.IsAtEnd(); i.Advance()) {
+    RenderProcessHost* render_process_host = i.GetCurrentValue();
+    if (HostZoomMap::GetForBrowserContext(
+            render_process_host->GetBrowserContext()) == this) {
+      render_process_host->Send(
+          new ViewMsg_SetZoomLevelForCurrentURL(scheme, host, level));
+    }
+  }
+}
+
 HostZoomMapImpl::~HostZoomMapImpl() {
 }
 
-HostZoomMapImpl::TemporaryZoomLevel::TemporaryZoomLevel(int process_id,
-                                                        int view_id,
-                                                        double level)
-    : render_process_id(process_id),
-      render_view_id(view_id),
-      zoom_level(level) {
-}
-
-HostZoomMapImpl::TemporaryZoomLevel::TemporaryZoomLevel(int process_id,
-                                                        int view_id)
-    : render_process_id(process_id),
-      render_view_id(view_id),
-      zoom_level(0.0) {
-}
-
-bool HostZoomMapImpl::TemporaryZoomLevel::operator==(
-    const TemporaryZoomLevel& other) const {
-  return other.render_process_id == render_process_id &&
-         other.render_view_id == render_view_id;
-}
-
 }  // namespace content