Fix leaks by providing a target destruction notification to the EventHandler, which gives it the opportunity to clean itself up.

http://crbug.com/147756
[email protected]
Review URL: https://chromiumcodereview.appspot.com/10916230

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@156227 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index ef8df72..e9aff8b 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -128,161 +128,6 @@
   container->SetProperty(internal::kUsesScreenCoordinatesKey, true);
 }
 
-// Creates each of the special window containers that holds windows of various
-// types in the shell UI.
-void CreateContainersInRootWindow(aura::RootWindow* root_window) {
-  // These containers are just used by PowerButtonController to animate groups
-  // of containers simultaneously without messing up the current transformations
-  // on those containers. These are direct children of the root window; all of
-  // the other containers are their children.
-  // Desktop and lock screen background containers are not part of the
-  // lock animation so they are not included in those animate groups.
-  // When screen is locked desktop background is moved to lock screen background
-  // container (moved back on unlock). We want to make sure that there's an
-  // opaque layer occluding the non-lock-screen layers.
-
-  CreateContainer(internal::kShellWindowId_SystemBackgroundContainer,
-                  "SystemBackgroundContainer", root_window);
-
-  aura::Window* desktop_background_containers = CreateContainer(
-      internal::kShellWindowId_DesktopBackgroundContainer,
-      "DesktopBackgroundContainer",
-      root_window);
-  SetChildWindowVisibilityChangesAnimated(desktop_background_containers);
-
-  aura::Window* non_lock_screen_containers = CreateContainer(
-      internal::kShellWindowId_NonLockScreenContainersContainer,
-      "NonLockScreenContainersContainer",
-      root_window);
-
-  aura::Window* lock_background_containers = CreateContainer(
-      internal::kShellWindowId_LockScreenBackgroundContainer,
-      "LockScreenBackgroundContainer",
-      root_window);
-  SetChildWindowVisibilityChangesAnimated(lock_background_containers);
-
-  aura::Window* lock_screen_containers = CreateContainer(
-      internal::kShellWindowId_LockScreenContainersContainer,
-      "LockScreenContainersContainer",
-      root_window);
-  aura::Window* lock_screen_related_containers = CreateContainer(
-      internal::kShellWindowId_LockScreenRelatedContainersContainer,
-      "LockScreenRelatedContainersContainer",
-      root_window);
-
-  CreateContainer(internal::kShellWindowId_UnparentedControlContainer,
-                  "UnparentedControlContainer",
-                  non_lock_screen_containers);
-
-  aura::Window* default_container = CreateContainer(
-      internal::kShellWindowId_DefaultContainer,
-      "DefaultContainer",
-      non_lock_screen_containers);
-  if (!internal::WorkspaceController::IsWorkspace2Enabled()) {
-    default_container->AddPreTargetHandler(
-        new ToplevelWindowEventHandler(default_container));
-  }
-  SetChildWindowVisibilityChangesAnimated(default_container);
-  SetUsesScreenCoordinates(default_container);
-
-  aura::Window* always_on_top_container = CreateContainer(
-      internal::kShellWindowId_AlwaysOnTopContainer,
-      "AlwaysOnTopContainer",
-      non_lock_screen_containers);
-  always_on_top_container->AddPreTargetHandler(
-      new ToplevelWindowEventHandler(always_on_top_container));
-  SetChildWindowVisibilityChangesAnimated(always_on_top_container);
-  SetUsesScreenCoordinates(always_on_top_container);
-
-  aura::Window* panel_container = CreateContainer(
-      internal::kShellWindowId_PanelContainer,
-      "PanelContainer",
-      non_lock_screen_containers);
-  SetUsesScreenCoordinates(panel_container);
-
-  aura::Window* launcher_container =
-      CreateContainer(internal::kShellWindowId_LauncherContainer,
-                      "LauncherContainer",
-                      non_lock_screen_containers);
-  SetUsesScreenCoordinates(launcher_container);
-
-  CreateContainer(internal::kShellWindowId_AppListContainer,
-                  "AppListContainer",
-                  non_lock_screen_containers);
-
-  aura::Window* modal_container = CreateContainer(
-      internal::kShellWindowId_SystemModalContainer,
-      "SystemModalContainer",
-      non_lock_screen_containers);
-  modal_container->AddPreTargetHandler(
-      new ToplevelWindowEventHandler(modal_container));
-  modal_container->SetLayoutManager(
-      new internal::SystemModalContainerLayoutManager(modal_container));
-  SetChildWindowVisibilityChangesAnimated(modal_container);
-  SetUsesScreenCoordinates(modal_container);
-
-  aura::Window* input_method_container = CreateContainer(
-      internal::kShellWindowId_InputMethodContainer,
-      "InputMethodContainer",
-      non_lock_screen_containers);
-  SetUsesScreenCoordinates(input_method_container);
-
-  // TODO(beng): Figure out if we can make this use
-  // SystemModalContainerEventFilter instead of stops_event_propagation.
-  aura::Window* lock_container = CreateContainer(
-      internal::kShellWindowId_LockScreenContainer,
-      "LockScreenContainer",
-      lock_screen_containers);
-  lock_container->SetLayoutManager(
-      new internal::BaseLayoutManager(root_window));
-  SetUsesScreenCoordinates(lock_container);
-  // TODO(beng): stopsevents
-
-  aura::Window* lock_modal_container = CreateContainer(
-      internal::kShellWindowId_LockSystemModalContainer,
-      "LockSystemModalContainer",
-      lock_screen_containers);
-  lock_modal_container->AddPreTargetHandler(
-      new ToplevelWindowEventHandler(lock_modal_container));
-  lock_modal_container->SetLayoutManager(
-      new internal::SystemModalContainerLayoutManager(lock_modal_container));
-  SetChildWindowVisibilityChangesAnimated(lock_modal_container);
-  SetUsesScreenCoordinates(lock_modal_container);
-
-  aura::Window* status_container =
-      CreateContainer(internal::kShellWindowId_StatusContainer,
-                      "StatusContainer",
-                      lock_screen_related_containers);
-  SetUsesScreenCoordinates(status_container);
-
-  aura::Window* settings_bubble_container = CreateContainer(
-      internal::kShellWindowId_SettingBubbleContainer,
-      "SettingBubbleContainer",
-      lock_screen_related_containers);
-  SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
-  SetUsesScreenCoordinates(settings_bubble_container);
-
-  aura::Window* menu_container = CreateContainer(
-      internal::kShellWindowId_MenuContainer,
-      "MenuContainer",
-      lock_screen_related_containers);
-  SetChildWindowVisibilityChangesAnimated(menu_container);
-  SetUsesScreenCoordinates(menu_container);
-
-  aura::Window* drag_drop_container = CreateContainer(
-      internal::kShellWindowId_DragImageAndTooltipContainer,
-      "DragImageAndTooltipContainer",
-      lock_screen_related_containers);
-  SetChildWindowVisibilityChangesAnimated(drag_drop_container);
-  SetUsesScreenCoordinates(drag_drop_container);
-
-  aura::Window* overlay_container = CreateContainer(
-      internal::kShellWindowId_OverlayContainer,
-      "OverlayContainer",
-      lock_screen_related_containers);
-  SetUsesScreenCoordinates(overlay_container);
-}
-
 }  // namespace
 
 namespace internal {
@@ -395,5 +240,168 @@
   }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// RootWindowController, private:
+
+void RootWindowController::CreateContainersInRootWindow(
+    aura::RootWindow* root_window) {
+  // These containers are just used by PowerButtonController to animate groups
+  // of containers simultaneously without messing up the current transformations
+  // on those containers. These are direct children of the root window; all of
+  // the other containers are their children.
+  // Desktop and lock screen background containers are not part of the
+  // lock animation so they are not included in those animate groups.
+  // When screen is locked desktop background is moved to lock screen background
+  // container (moved back on unlock). We want to make sure that there's an
+  // opaque layer occluding the non-lock-screen layers.
+
+  CreateContainer(internal::kShellWindowId_SystemBackgroundContainer,
+                  "SystemBackgroundContainer", root_window);
+
+  aura::Window* desktop_background_containers = CreateContainer(
+      internal::kShellWindowId_DesktopBackgroundContainer,
+      "DesktopBackgroundContainer",
+      root_window);
+  SetChildWindowVisibilityChangesAnimated(desktop_background_containers);
+
+  aura::Window* non_lock_screen_containers = CreateContainer(
+      internal::kShellWindowId_NonLockScreenContainersContainer,
+      "NonLockScreenContainersContainer",
+      root_window);
+
+  aura::Window* lock_background_containers = CreateContainer(
+      internal::kShellWindowId_LockScreenBackgroundContainer,
+      "LockScreenBackgroundContainer",
+      root_window);
+  SetChildWindowVisibilityChangesAnimated(lock_background_containers);
+
+  aura::Window* lock_screen_containers = CreateContainer(
+      internal::kShellWindowId_LockScreenContainersContainer,
+      "LockScreenContainersContainer",
+      root_window);
+  aura::Window* lock_screen_related_containers = CreateContainer(
+      internal::kShellWindowId_LockScreenRelatedContainersContainer,
+      "LockScreenRelatedContainersContainer",
+      root_window);
+
+  CreateContainer(internal::kShellWindowId_UnparentedControlContainer,
+                  "UnparentedControlContainer",
+                  non_lock_screen_containers);
+
+  aura::Window* default_container = CreateContainer(
+      internal::kShellWindowId_DefaultContainer,
+      "DefaultContainer",
+      non_lock_screen_containers);
+  if (!internal::WorkspaceController::IsWorkspace2Enabled()) {
+    default_container_handler_.reset(
+        new ToplevelWindowEventHandler(default_container));
+    default_container->AddPreTargetHandler(default_container_handler_.get());
+  }
+  SetChildWindowVisibilityChangesAnimated(default_container);
+  SetUsesScreenCoordinates(default_container);
+
+  aura::Window* always_on_top_container = CreateContainer(
+      internal::kShellWindowId_AlwaysOnTopContainer,
+      "AlwaysOnTopContainer",
+      non_lock_screen_containers);
+  always_on_top_container_handler_.reset(
+      new ToplevelWindowEventHandler(always_on_top_container));
+  always_on_top_container->AddPreTargetHandler(
+      always_on_top_container_handler_.get());
+  SetChildWindowVisibilityChangesAnimated(always_on_top_container);
+  SetUsesScreenCoordinates(always_on_top_container);
+
+  aura::Window* panel_container = CreateContainer(
+      internal::kShellWindowId_PanelContainer,
+      "PanelContainer",
+      non_lock_screen_containers);
+  SetUsesScreenCoordinates(panel_container);
+
+  aura::Window* launcher_container =
+      CreateContainer(internal::kShellWindowId_LauncherContainer,
+                      "LauncherContainer",
+                      non_lock_screen_containers);
+  SetUsesScreenCoordinates(launcher_container);
+
+  CreateContainer(internal::kShellWindowId_AppListContainer,
+                  "AppListContainer",
+                  non_lock_screen_containers);
+
+  aura::Window* modal_container = CreateContainer(
+      internal::kShellWindowId_SystemModalContainer,
+      "SystemModalContainer",
+      non_lock_screen_containers);
+  modal_container_handler_.reset(
+      new ToplevelWindowEventHandler(modal_container));
+  modal_container->AddPreTargetHandler(modal_container_handler_.get());
+  modal_container->SetLayoutManager(
+      new internal::SystemModalContainerLayoutManager(modal_container));
+  SetChildWindowVisibilityChangesAnimated(modal_container);
+  SetUsesScreenCoordinates(modal_container);
+
+  aura::Window* input_method_container = CreateContainer(
+      internal::kShellWindowId_InputMethodContainer,
+      "InputMethodContainer",
+      non_lock_screen_containers);
+  SetUsesScreenCoordinates(input_method_container);
+
+  // TODO(beng): Figure out if we can make this use
+  // SystemModalContainerEventFilter instead of stops_event_propagation.
+  aura::Window* lock_container = CreateContainer(
+      internal::kShellWindowId_LockScreenContainer,
+      "LockScreenContainer",
+      lock_screen_containers);
+  lock_container->SetLayoutManager(
+      new internal::BaseLayoutManager(root_window));
+  SetUsesScreenCoordinates(lock_container);
+  // TODO(beng): stopsevents
+
+  aura::Window* lock_modal_container = CreateContainer(
+      internal::kShellWindowId_LockSystemModalContainer,
+      "LockSystemModalContainer",
+      lock_screen_containers);
+  lock_modal_container_handler_.reset(
+      new ToplevelWindowEventHandler(lock_modal_container));
+  lock_modal_container->AddPreTargetHandler(
+      lock_modal_container_handler_.get());
+  lock_modal_container->SetLayoutManager(
+      new internal::SystemModalContainerLayoutManager(lock_modal_container));
+  SetChildWindowVisibilityChangesAnimated(lock_modal_container);
+  SetUsesScreenCoordinates(lock_modal_container);
+
+  aura::Window* status_container =
+      CreateContainer(internal::kShellWindowId_StatusContainer,
+                      "StatusContainer",
+                      lock_screen_related_containers);
+  SetUsesScreenCoordinates(status_container);
+
+  aura::Window* settings_bubble_container = CreateContainer(
+      internal::kShellWindowId_SettingBubbleContainer,
+      "SettingBubbleContainer",
+      lock_screen_related_containers);
+  SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
+  SetUsesScreenCoordinates(settings_bubble_container);
+
+  aura::Window* menu_container = CreateContainer(
+      internal::kShellWindowId_MenuContainer,
+      "MenuContainer",
+      lock_screen_related_containers);
+  SetChildWindowVisibilityChangesAnimated(menu_container);
+  SetUsesScreenCoordinates(menu_container);
+
+  aura::Window* drag_drop_container = CreateContainer(
+      internal::kShellWindowId_DragImageAndTooltipContainer,
+      "DragImageAndTooltipContainer",
+      lock_screen_related_containers);
+  SetChildWindowVisibilityChangesAnimated(drag_drop_container);
+  SetUsesScreenCoordinates(drag_drop_container);
+
+  aura::Window* overlay_container = CreateContainer(
+      internal::kShellWindowId_OverlayContainer,
+      "OverlayContainer",
+      lock_screen_related_containers);
+  SetUsesScreenCoordinates(overlay_container);
+}
+
 }  // namespace internal
 }  // namespace ash
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index c17d85a..27f396d1 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -21,6 +21,7 @@
 }  // namespace aura
 
 namespace ash {
+class ToplevelWindowEventHandler;
 namespace internal {
 
 class EventClientImpl;
@@ -75,6 +76,10 @@
   void MoveWindowsTo(aura::RootWindow* dest);
 
  private:
+  // Creates each of the special window containers that holds windows of various
+  // types in the shell UI.
+  void CreateContainersInRootWindow(aura::RootWindow* root_window);
+
   scoped_ptr<aura::RootWindow> root_window_;
   internal::RootWindowLayoutManager* root_window_layout_;
 
@@ -83,6 +88,12 @@
   scoped_ptr<internal::ScreenDimmer> screen_dimmer_;
   scoped_ptr<internal::WorkspaceController> workspace_controller_;
 
+  // We need to own event handlers for various containers.
+  scoped_ptr<ToplevelWindowEventHandler> default_container_handler_;
+  scoped_ptr<ToplevelWindowEventHandler> always_on_top_container_handler_;
+  scoped_ptr<ToplevelWindowEventHandler> modal_container_handler_;
+  scoped_ptr<ToplevelWindowEventHandler> lock_modal_container_handler_;
+
   DISALLOW_COPY_AND_ASSIGN(RootWindowController);
 };
 
diff --git a/ash/wm/workspace/workspace2.cc b/ash/wm/workspace/workspace2.cc
index a145521..8e1ac5e 100644
--- a/ash/wm/workspace/workspace2.cc
+++ b/ash/wm/workspace/workspace2.cc
@@ -31,7 +31,7 @@
   window_->layer()->SetMasksToBounds(true);
   window_->Hide();
   window_->SetParent(parent);
-  window_->AddPreTargetHandler(event_handler_);
+  window_->AddPreTargetHandler(event_handler_.get());
   window_->SetProperty(internal::kUsesScreenCoordinatesKey, true);
 }
 
@@ -47,7 +47,6 @@
   window_->SetEventFilter(NULL);
   aura::Window* window = window_;
   window_ = NULL;
-  event_handler_ = NULL;
   return window;
 }
 
diff --git a/ash/wm/workspace/workspace2.h b/ash/wm/workspace/workspace2.h
index 6fbfe3b..92e8e725 100644
--- a/ash/wm/workspace/workspace2.h
+++ b/ash/wm/workspace/workspace2.h
@@ -9,6 +9,7 @@
 
 #include "ash/ash_export.h"
 #include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
 
 namespace aura {
 class Window;
@@ -60,8 +61,7 @@
   // Our Window, owned by |parent| passed to the constructor.
   aura::Window* window_;
 
-  // Owned by |window_|.
-  WorkspaceEventHandler* event_handler_;
+  scoped_ptr<WorkspaceEventHandler> event_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(Workspace2);
 };
diff --git a/tools/heapcheck/suppressions.txt b/tools/heapcheck/suppressions.txt
index f0bc1917..f8b1d0f 100644
--- a/tools/heapcheck/suppressions.txt
+++ b/tools/heapcheck/suppressions.txt
@@ -1605,24 +1605,6 @@
    fun:PluginPrefsTest_UnifiedPepperFlashState_Test::TestBody
 }
 {
-   bug_147756_a
-   Heapcheck:Leak
-   fun:Workspace2
-   fun:ash::internal::WorkspaceManager2::CreateWorkspace
-   fun:WorkspaceManager2
-   fun:WorkspaceController
-   fun:ash::internal::RootWindowController::InitLayoutManagers
-   fun:ash::Shell::InitRootWindowController
-   fun:ash::Shell::Init
-}
-{
-   bug_147756_b
-   Heapcheck:Leak
-   fun:ash::::CreateContainersInRootWindow
-   fun:ash::internal::RootWindowController::CreateContainers
-   fun:ash::Shell::Init
-}
-{
    bug_148589
    Heapcheck:Leak
    fun:ui::Clipboard::GetForCurrentThread
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index cc82235..c7fce3a3 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -5987,26 +5987,6 @@
    fun:_ZN11PluginPrefs30EnablePluginIfPossibleCallbackEbRK8FilePathRKN4base8CallbackIFvbEEEP12PluginFinder
 }
 {
-   bug_147756_a
-   Memcheck:Leak
-   fun:_Znw*
-   fun:_ZN3ash8internal10Workspace2C1EPNS0_17WorkspaceManager2EPN4aura6WindowEb
-   fun:_ZN3ash8internal17WorkspaceManager215CreateWorkspaceEb
-   fun:_ZN3ash8internal17WorkspaceManager2C1EPN4aura6WindowE
-   fun:_ZN3ash8internal19WorkspaceControllerC1EPN4aura6WindowE
-   fun:_ZN3ash8internal20RootWindowController18InitLayoutManagersEv
-   fun:_ZN3ash5Shell24InitRootWindowControllerEPNS_8internal20RootWindowControllerE
-   fun:_ZN3ash5Shell4InitEv
-}
-{
-   bug_147756_b
-   Memcheck:Leak
-   fun:_Znw*
-   fun:_ZN3ash*CreateContainersInRootWindowEPN4aura10RootWindowE
-   fun:_ZN3ash8internal20RootWindowController16CreateContainersEv
-   fun:_ZN3ash5Shell4InitEv
-}
-{
    bug_148475
    Memcheck:Uninitialized
    ...