Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / apps / native_app_window_views.cc
index aacb7cd..e465d1f 100644 (file)
@@ -4,13 +4,13 @@
 
 #include "chrome/browser/ui/views/apps/native_app_window_views.h"
 
-#include "apps/shell_window.h"
-#include "apps/ui/views/shell_window_frame_view.h"
+#include "apps/app_window.h"
+#include "apps/ui/views/app_window_frame_view.h"
 #include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/app_mode/app_mode_utils.h"
+#include "chrome/browser/chrome_page_zoom.h"
 #include "chrome/browser/extensions/extension_host.h"
 #include "chrome/browser/favicon/favicon_tab_helper.h"
 #include "chrome/browser/profiles/profile.h"
@@ -18,6 +18,7 @@
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/views/apps/shaped_app_window_targeter.h"
 #include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views.h"
+#include "chrome/browser/ui/views/frame/taskbar_decorator.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/common/chrome_switches.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/views/controls/webview/webview.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/non_client_view.h"
-
-#if defined(OS_WIN)
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/web_applications/web_app_ui.h"
-#include "chrome/browser/web_applications/web_app_win.h"
-#include "ui/base/win/shell.h"
-#include "ui/views/win/hwnd_util.h"
-#endif
+#include "ui/wm/public/easy_resize_window_targeter.h"
 
 #if defined(OS_LINUX)
 #include "chrome/browser/shell_integration_linux.h"
@@ -68,7 +62,7 @@
 #include "ui/aura/window.h"
 #endif
 
-using apps::ShellWindow;
+using apps::AppWindow;
 
 namespace {
 
@@ -84,71 +78,71 @@ struct AcceleratorMapping {
   int modifiers;
   int command_id;
 };
+
 const AcceleratorMapping kAppWindowAcceleratorMap[] = {
   { ui::VKEY_W, ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW },
   { ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_CLOSE_WINDOW },
   { ui::VKEY_F4, ui::EF_ALT_DOWN, IDC_CLOSE_WINDOW },
 };
 
+// These accelerators will only be available in kiosk mode. These allow the
+// user to manually zoom app windows. This is only necessary in kiosk mode
+// (in normal mode, the user can zoom via the screen magnifier).
+// TODO(xiyuan): Write a test for kiosk accelerators.
+const AcceleratorMapping kAppWindowKioskAppModeAcceleratorMap[] = {
+  { ui::VKEY_OEM_MINUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
+  { ui::VKEY_OEM_MINUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+    IDC_ZOOM_MINUS },
+  { ui::VKEY_SUBTRACT, ui::EF_CONTROL_DOWN, IDC_ZOOM_MINUS },
+  { ui::VKEY_OEM_PLUS, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
+  { ui::VKEY_OEM_PLUS, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
+  { ui::VKEY_ADD, ui::EF_CONTROL_DOWN, IDC_ZOOM_PLUS },
+  { ui::VKEY_0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
+  { ui::VKEY_NUMPAD0, ui::EF_CONTROL_DOWN, IDC_ZOOM_NORMAL },
+};
+
+void AddAcceleratorsFromMapping(const AcceleratorMapping mapping[],
+                                size_t mapping_length,
+                                std::map<ui::Accelerator, int>* accelerators) {
+  for (size_t i = 0; i < mapping_length; ++i) {
+    ui::Accelerator accelerator(mapping[i].keycode, mapping[i].modifiers);
+    (*accelerators)[accelerator] = mapping[i].command_id;
+  }
+}
+
 const std::map<ui::Accelerator, int>& GetAcceleratorTable() {
   typedef std::map<ui::Accelerator, int> AcceleratorMap;
   CR_DEFINE_STATIC_LOCAL(AcceleratorMap, accelerators, ());
   if (accelerators.empty()) {
-    for (size_t i = 0; i < arraysize(kAppWindowAcceleratorMap); ++i) {
-      ui::Accelerator accelerator(kAppWindowAcceleratorMap[i].keycode,
-                                  kAppWindowAcceleratorMap[i].modifiers);
-      accelerators[accelerator] = kAppWindowAcceleratorMap[i].command_id;
+    AddAcceleratorsFromMapping(
+        kAppWindowAcceleratorMap,
+        arraysize(kAppWindowAcceleratorMap),
+        &accelerators);
+
+    // Add accelerators for kiosk mode.
+    if (chrome::IsRunningInForcedAppMode()) {
+      AddAcceleratorsFromMapping(
+          kAppWindowKioskAppModeAcceleratorMap,
+          arraysize(kAppWindowKioskAppModeAcceleratorMap),
+          &accelerators);
     }
   }
   return accelerators;
 }
 
-#if defined(OS_WIN)
-void CreateIconAndSetRelaunchDetails(
-    const base::FilePath web_app_path,
-    const base::FilePath icon_file,
-    const ShellIntegration::ShortcutInfo& shortcut_info,
-    const HWND hwnd) {
-  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
-
-  // Set the relaunch data so "Pin this program to taskbar" has the app's
-  // information.
-  CommandLine command_line = ShellIntegration::CommandLineArgsForLauncher(
-      shortcut_info.url,
-      shortcut_info.extension_id,
-      shortcut_info.profile_path);
-
-  base::FilePath chrome_exe;
-  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
-    NOTREACHED();
-    return;
-  }
-  command_line.SetProgram(chrome_exe);
-  ui::win::SetRelaunchDetailsForWindow(command_line.GetCommandLineString(),
-      shortcut_info.title, hwnd);
-
-  if (!base::PathExists(web_app_path) &&
-      !base::CreateDirectory(web_app_path))
-    return;
-
-  ui::win::SetAppIconForWindow(icon_file.value(), hwnd);
-  web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info.favicon);
-}
-#endif
-
 #if defined(USE_ASH)
 // This class handles a user's fullscreen request (Shift+F4/F4).
 class NativeAppWindowStateDelegate : public ash::wm::WindowStateDelegate,
                                      public ash::wm::WindowStateObserver,
                                      public aura::WindowObserver {
  public:
-  NativeAppWindowStateDelegate(ShellWindow* shell_window,
+  NativeAppWindowStateDelegate(AppWindow* app_window,
                                apps::NativeAppWindow* native_app_window)
-      : shell_window_(shell_window),
+      : app_window_(app_window),
         window_state_(
             ash::wm::GetWindowState(native_app_window->GetNativeWindow())) {
     // Add a window state observer to exit fullscreen properly in case
-    // fullscreen is exited without going through ShellWindow::Restore(). This
+    // fullscreen is exited without going through AppWindow::Restore(). This
     // is the case when exiting immersive fullscreen via the "Restore" window
     // control.
     // TODO(pkotwicz): This is a hack. Remove ASAP. http://crbug.com/319048
@@ -168,25 +162,24 @@ class NativeAppWindowStateDelegate : public ash::wm::WindowStateDelegate,
     // Windows which cannot be maximized should not be fullscreened.
     DCHECK(window_state->IsFullscreen() || window_state->CanMaximize());
     if (window_state->IsFullscreen())
-      shell_window_->Restore();
+      app_window_->Restore();
     else if (window_state->CanMaximize())
-      shell_window_->OSFullscreen();
+      app_window_->OSFullscreen();
     return true;
   }
 
   // Overridden from ash::wm::WindowStateObserver:
-  virtual void OnWindowShowTypeChanged(
+  virtual void OnPostWindowShowTypeChange(
       ash::wm::WindowState* window_state,
       ash::wm::WindowShowType old_type) OVERRIDE {
-    if (!window_state->IsFullscreen() &&
-        !window_state->IsMinimized() &&
-        shell_window_->GetBaseWindow()->IsFullscreenOrPending()) {
-      shell_window_->Restore();
+    if (!window_state->IsFullscreen() && !window_state->IsMinimized() &&
+        app_window_->GetBaseWindow()->IsFullscreenOrPending()) {
+      app_window_->Restore();
       // Usually OnNativeWindowChanged() is called when the window bounds are
       // changed as a result of a show type change. Because the change in show
       // type has already occurred, we need to call OnNativeWindowChanged()
       // explicitly.
-      shell_window_->OnNativeWindowChanged();
+      app_window_->OnNativeWindowChanged();
     }
   }
 
@@ -198,7 +191,7 @@ class NativeAppWindowStateDelegate : public ash::wm::WindowStateDelegate,
   }
 
   // Not owned.
-  ShellWindow* shell_window_;
+  AppWindow* app_window_;
   ash::wm::WindowState* window_state_;
 
   DISALLOW_COPY_AND_ASSIGN(NativeAppWindowStateDelegate);
@@ -214,31 +207,37 @@ NativeAppWindowViews::NativeAppWindowViews()
       weak_ptr_factory_(this) {
 }
 
-void NativeAppWindowViews::Init(
-    apps::ShellWindow* shell_window,
-    const ShellWindow::CreateParams& create_params) {
-  shell_window_ = shell_window;
-  frameless_ = create_params.frame == ShellWindow::FRAME_NONE;
+void NativeAppWindowViews::Init(apps::AppWindow* app_window,
+                                const AppWindow::CreateParams& create_params) {
+  app_window_ = app_window;
+  frameless_ = create_params.frame == AppWindow::FRAME_NONE;
   transparent_background_ = create_params.transparent_background;
   resizable_ = create_params.resizable;
   Observe(web_contents());
 
   window_ = new views::Widget;
-  if (create_params.window_type == ShellWindow::WINDOW_TYPE_PANEL ||
-      create_params.window_type == ShellWindow::WINDOW_TYPE_V1_PANEL) {
+  if (create_params.window_type == AppWindow::WINDOW_TYPE_PANEL ||
+      create_params.window_type == AppWindow::WINDOW_TYPE_V1_PANEL) {
     InitializePanelWindow(create_params);
   } else {
     InitializeDefaultWindow(create_params);
   }
-  extension_keybinding_registry_.reset(
-      new ExtensionKeybindingRegistryViews(
-          profile(),
-          window_->GetFocusManager(),
-          extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
-          shell_window_));
+  extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryViews(
+      Profile::FromBrowserContext(browser_context()),
+      window_->GetFocusManager(),
+      extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY,
+      app_window_));
 
   OnViewWasResized();
   window_->AddObserver(this);
+
+#if defined(OS_WIN)
+  if (ShouldUseChromeStyleFrame() &&
+      chrome::GetHostDesktopTypeForNativeWindow(window_->GetNativeWindow()) !=
+      chrome::HOST_DESKTOP_TYPE_ASH) {
+    InstallEasyResizeTargeterOnContainer();
+  }
+#endif
 }
 
 NativeAppWindowViews::~NativeAppWindowViews() {
@@ -250,7 +249,7 @@ void NativeAppWindowViews::OnBeforeWidgetInit(
     views::Widget* widget) {}
 
 void NativeAppWindowViews::InitializeDefaultWindow(
-    const ShellWindow::CreateParams& create_params) {
+    const AppWindow::CreateParams& create_params) {
   std::string app_name =
       web_app::GenerateApplicationNameFromExtensionId(extension()->id());
 
@@ -301,55 +300,31 @@ void NativeAppWindowViews::InitializeDefaultWindow(
   views::FocusManager* focus_manager = GetFocusManager();
   const std::map<ui::Accelerator, int>& accelerator_table =
       GetAcceleratorTable();
+  const bool is_kiosk_app_mode = chrome::IsRunningInForcedAppMode();
+
+  // Ensures that kiosk mode accelerators are enabled when in kiosk mode (to be
+  // future proof). This is needed because GetAcceleratorTable() uses a static
+  // to store data and only checks kiosk mode once. If a platform app is
+  // launched before kiosk mode starts, the kiosk accelerators will not be
+  // registered. This DCHECK catches the case.
+  DCHECK(!is_kiosk_app_mode ||
+         accelerator_table.size() ==
+             arraysize(kAppWindowAcceleratorMap) +
+                 arraysize(kAppWindowKioskAppModeAcceleratorMap));
+
   for (std::map<ui::Accelerator, int>::const_iterator iter =
            accelerator_table.begin();
        iter != accelerator_table.end(); ++iter) {
+    if (is_kiosk_app_mode && !chrome::IsCommandAllowedInAppMode(iter->second))
+      continue;
+
     focus_manager->RegisterAccelerator(
         iter->first, ui::AcceleratorManager::kNormalPriority, this);
   }
-
-#if defined(OS_WIN)
-  base::string16 app_name_wide = base::UTF8ToWide(app_name);
-  HWND hwnd = GetNativeAppWindowHWND();
-  ui::win::SetAppIdForWindow(ShellIntegration::GetAppModelIdForProfile(
-      app_name_wide, profile()->GetPath()), hwnd);
-
-  web_app::UpdateShortcutInfoAndIconForApp(
-      *extension(), profile(),
-      base::Bind(&NativeAppWindowViews::OnShortcutInfoLoaded,
-                 weak_ptr_factory_.GetWeakPtr()));
-#endif
-}
-
-#if defined(OS_WIN)
-void NativeAppWindowViews::OnShortcutInfoLoaded(
-    const ShellIntegration::ShortcutInfo& shortcut_info) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  HWND hwnd = GetNativeAppWindowHWND();
-
-  // Set window's icon to the one we're about to create/update in the web app
-  // path. The icon cache will refresh on icon creation.
-  base::FilePath web_app_path = web_app::GetWebAppDataDirectory(
-      shortcut_info.profile_path, shortcut_info.extension_id,
-      shortcut_info.url);
-  base::FilePath icon_file = web_app_path
-      .Append(web_app::internals::GetSanitizedFileName(shortcut_info.title))
-      .ReplaceExtension(FILE_PATH_LITERAL(".ico"));
-
-  content::BrowserThread::PostBlockingPoolTask(
-      FROM_HERE,
-      base::Bind(&CreateIconAndSetRelaunchDetails,
-                 web_app_path, icon_file, shortcut_info, hwnd));
 }
 
-HWND NativeAppWindowViews::GetNativeAppWindowHWND() const {
-  return views::HWNDForWidget(window_->GetTopLevelWidget());
-}
-#endif
-
 void NativeAppWindowViews::InitializePanelWindow(
-    const ShellWindow::CreateParams& create_params) {
+    const AppWindow::CreateParams& create_params) {
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_PANEL);
   params.delegate = this;
 
@@ -414,7 +389,15 @@ bool NativeAppWindowViews::ShouldUseChromeStyleFrame() const {
       switches::kAppsUseNativeFrame);
 }
 
-apps::ShellWindowFrameView* NativeAppWindowViews::CreateShellWindowFrameView() {
+void NativeAppWindowViews::InstallEasyResizeTargeterOnContainer() const {
+  aura::Window* root_window = window_->GetNativeWindow()->GetRootWindow();
+  gfx::Insets inset(kResizeInsideBoundsSize, kResizeInsideBoundsSize,
+                    kResizeInsideBoundsSize, kResizeInsideBoundsSize);
+  root_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
+      new wm::EasyResizeWindowTargeter(root_window, inset, inset)));
+}
+
+apps::AppWindowFrameView* NativeAppWindowViews::CreateAppWindowFrameView() {
   // By default the user can resize the window from slightly inside the bounds.
   int resize_inside_bounds_size = kResizeInsideBoundsSize;
   int resize_outside_bounds_size = 0;
@@ -430,7 +413,7 @@ apps::ShellWindowFrameView* NativeAppWindowViews::CreateShellWindowFrameView() {
     resize_area_corner_size = ash::kResizeAreaCornerSize;
   }
 #endif
-  apps::ShellWindowFrameView* frame_view = new apps::ShellWindowFrameView(this);
+  apps::AppWindowFrameView* frame_view = new apps::AppWindowFrameView(this);
   frame_view->Init(window_,
                    resize_inside_bounds_size,
                    resize_outside_bounds_size,
@@ -560,7 +543,7 @@ void NativeAppWindowViews::FlashFrame(bool flash) {
 }
 
 bool NativeAppWindowViews::IsAlwaysOnTop() const {
-  if (shell_window_->window_type_is_panel()) {
+  if (app_window_->window_type_is_panel()) {
 #if defined(USE_ASH)
     return ash::wm::GetWindowState(window_->GetNativeWindow())->
         panel_attached();
@@ -580,9 +563,9 @@ void NativeAppWindowViews::ShowContextMenuForView(
     views::View* source,
     const gfx::Point& p,
     ui::MenuSourceType source_type) {
-#if defined(USE_ASH)
-  scoped_ptr<ui::MenuModel> model = CreateMultiUserContextMenu(
-      shell_window_->GetNativeWindow());
+#if defined(USE_ASH) & defined(OS_CHROMEOS)
+  scoped_ptr<ui::MenuModel> model =
+      CreateMultiUserContextMenu(app_window_->GetNativeWindow());
   if (!model.get())
     return;
 
@@ -609,9 +592,9 @@ gfx::NativeView NativeAppWindowViews::GetHostView() const {
 }
 
 gfx::Point NativeAppWindowViews::GetDialogPosition(const gfx::Size& size) {
-  gfx::Size shell_window_size = window_->GetWindowBoundsInScreen().size();
-  return gfx::Point(shell_window_size.width() / 2 - size.width() / 2,
-                    shell_window_size.height() / 2 - size.height() / 2);
+  gfx::Size app_window_size = window_->GetWindowBoundsInScreen().size();
+  return gfx::Point(app_window_size.width() / 2 - size.width() / 2,
+                    app_window_size.height() / 2 - size.height() / 2);
 }
 
 gfx::Size NativeAppWindowViews::GetMaximumDialogSize() {
@@ -638,7 +621,7 @@ void NativeAppWindowViews::OnViewWasResized() {
 // WidgetDelegate implementation.
 
 void NativeAppWindowViews::OnWidgetMove() {
-  shell_window_->OnNativeWindowChanged();
+  app_window_->OnNativeWindowChanged();
 }
 
 views::View* NativeAppWindowViews::GetInitiallyFocusedView() {
@@ -646,24 +629,24 @@ views::View* NativeAppWindowViews::GetInitiallyFocusedView() {
 }
 
 bool NativeAppWindowViews::CanResize() const {
-  return resizable_ && !shell_window_->size_constraints().HasFixedSize();
+  return resizable_ && !app_window_->size_constraints().HasFixedSize();
 }
 
 bool NativeAppWindowViews::CanMaximize() const {
-  return resizable_ && !shell_window_->size_constraints().HasMaximumSize() &&
-      !shell_window_->window_type_is_panel();
+  return resizable_ && !app_window_->size_constraints().HasMaximumSize() &&
+         !app_window_->window_type_is_panel();
 }
 
 base::string16 NativeAppWindowViews::GetWindowTitle() const {
-  return shell_window_->GetTitle();
+  return app_window_->GetTitle();
 }
 
 bool NativeAppWindowViews::ShouldShowWindowTitle() const {
-  return shell_window_->window_type() == ShellWindow::WINDOW_TYPE_V1_PANEL;
+  return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL;
 }
 
 gfx::ImageSkia NativeAppWindowViews::GetWindowAppIcon() {
-  gfx::Image app_icon = shell_window_->app_icon();
+  gfx::Image app_icon = app_window_->app_icon();
   if (app_icon.IsEmpty())
     return GetWindowIcon();
   else
@@ -671,7 +654,7 @@ gfx::ImageSkia NativeAppWindowViews::GetWindowAppIcon() {
 }
 
 gfx::ImageSkia NativeAppWindowViews::GetWindowIcon() {
-  content::WebContents* web_contents = shell_window_->web_contents();
+  content::WebContents* web_contents = app_window_->web_contents();
   if (web_contents) {
     FaviconTabHelper* favicon_tab_helper =
         FaviconTabHelper::FromWebContents(web_contents);
@@ -683,18 +666,18 @@ gfx::ImageSkia NativeAppWindowViews::GetWindowIcon() {
 }
 
 bool NativeAppWindowViews::ShouldShowWindowIcon() const {
-  return shell_window_->window_type() == ShellWindow::WINDOW_TYPE_V1_PANEL;
+  return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL;
 }
 
 void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect& bounds,
                                                ui::WindowShowState show_state) {
   views::WidgetDelegate::SaveWindowPlacement(bounds, show_state);
-  shell_window_->OnNativeWindowChanged();
+  app_window_->OnNativeWindowChanged();
 }
 
 void NativeAppWindowViews::DeleteDelegate() {
   window_->RemoveObserver(this);
-  shell_window_->OnNativeClose();
+  app_window_->OnNativeClose();
 }
 
 views::Widget* NativeAppWindowViews::GetWidget() {
@@ -717,9 +700,9 @@ views::NonClientFrameView* NativeAppWindowViews::CreateNonClientFrameView(
     // WindowStateDelegate if one is not already set.
     ash::wm::GetWindowState(GetNativeWindow())->SetDelegate(
         scoped_ptr<ash::wm::WindowStateDelegate>(
-            new NativeAppWindowStateDelegate(shell_window_, this)).Pass());
+            new NativeAppWindowStateDelegate(app_window_, this)).Pass());
 
-    if (shell_window_->window_type_is_panel()) {
+    if (app_window_->window_type_is_panel()) {
       ash::PanelFrameView::FrameType frame_type = frameless_ ?
           ash::PanelFrameView::FRAME_NONE : ash::PanelFrameView::FRAME_ASH;
       views::NonClientFrameView* frame_view =
@@ -748,7 +731,7 @@ views::NonClientFrameView* NativeAppWindowViews::CreateNonClientFrameView(
   }
 #endif
   if (ShouldUseChromeStyleFrame())
-    return CreateShellWindowFrameView();
+    return CreateAppWindowFrameView();
   return views::WidgetDelegateView::CreateNonClientFrameView(widget);
 }
 
@@ -765,7 +748,7 @@ bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling(
     const gfx::Point& location) {
 #if defined(USE_AURA)
   if (child->Contains(web_view_->web_contents()->GetView()->GetNativeView())) {
-    // Shell window should claim mouse events that fall within the draggable
+    // App window should claim mouse events that fall within the draggable
     // region.
     return !draggable_region_.get() ||
            !draggable_region_->contains(location.x(), location.y());
@@ -779,14 +762,14 @@ bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling(
 
 void NativeAppWindowViews::OnWidgetVisibilityChanged(views::Widget* widget,
                                                      bool visible) {
-  shell_window_->OnNativeWindowChanged();
+  app_window_->OnNativeWindowChanged();
 }
 
 void NativeAppWindowViews::OnWidgetActivationChanged(views::Widget* widget,
                                                      bool active) {
-  shell_window_->OnNativeWindowChanged();
+  app_window_->OnNativeWindowChanged();
   if (active)
-    shell_window_->OnNativeWindowActivated();
+    app_window_->OnNativeWindowActivated();
 }
 
 // WebContentsObserver implementation.
@@ -836,11 +819,11 @@ gfx::Size NativeAppWindowViews::GetPreferredSize() {
 }
 
 gfx::Size NativeAppWindowViews::GetMinimumSize() {
-  return shell_window_->size_constraints().GetMinimumSize();
+  return app_window_->size_constraints().GetMinimumSize();
 }
 
 gfx::Size NativeAppWindowViews::GetMaximumSize() {
-  return shell_window_->size_constraints().GetMaximumSize();
+  return app_window_->size_constraints().GetMaximumSize();
 }
 
 void NativeAppWindowViews::OnFocus() {
@@ -859,6 +842,18 @@ bool NativeAppWindowViews::AcceleratorPressed(
     case IDC_CLOSE_WINDOW:
       Close();
       return true;
+    case IDC_ZOOM_MINUS:
+      chrome_page_zoom::Zoom(web_view_->GetWebContents(),
+                             content::PAGE_ZOOM_OUT);
+      return true;
+    case IDC_ZOOM_NORMAL:
+      chrome_page_zoom::Zoom(web_view_->GetWebContents(),
+                             content::PAGE_ZOOM_RESET);
+      return true;
+    case IDC_ZOOM_PLUS:
+      chrome_page_zoom::Zoom(web_view_->GetWebContents(),
+                             content::PAGE_ZOOM_IN);
+      return true;
     default:
       NOTREACHED() << "Unknown accelerator sent to app window.";
   }
@@ -869,9 +864,9 @@ bool NativeAppWindowViews::AcceleratorPressed(
 
 void NativeAppWindowViews::SetFullscreen(int fullscreen_types) {
   // Fullscreen not supported by panels.
-  if (shell_window_->window_type_is_panel())
+  if (app_window_->window_type_is_panel())
     return;
-  is_fullscreen_ = (fullscreen_types != ShellWindow::FULLSCREEN_TYPE_NONE);
+  is_fullscreen_ = (fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE);
   window_->SetFullscreen(is_fullscreen_);
 
 #if defined(USE_ASH)
@@ -880,13 +875,13 @@ void NativeAppWindowViews::SetFullscreen(int fullscreen_types) {
     // fullscreen is the fullscreen type used by the OS.
     immersive_fullscreen_controller_->SetEnabled(
         ash::ImmersiveFullscreenController::WINDOW_TYPE_PACKAGED_APP,
-        (fullscreen_types & ShellWindow::FULLSCREEN_TYPE_OS) != 0);
+        (fullscreen_types & AppWindow::FULLSCREEN_TYPE_OS) != 0);
     // Autohide the shelf instead of hiding the shelf completely when only in
     // OS fullscreen.
     ash::wm::WindowState* window_state =
         ash::wm::GetWindowState(window_->GetNativeWindow());
-    window_state->set_hide_shelf_when_fullscreen(
-        fullscreen_types != ShellWindow::FULLSCREEN_TYPE_OS);
+    window_state->set_hide_shelf_when_fullscreen(fullscreen_types !=
+                                                 AppWindow::FULLSCREEN_TYPE_OS);
     DCHECK(ash::Shell::HasInstance());
     ash::Shell::GetInstance()->UpdateShelfVisibility();
   }
@@ -902,7 +897,7 @@ bool NativeAppWindowViews::IsFullscreenOrPending() const {
 }
 
 bool NativeAppWindowViews::IsDetached() const {
-  if (!shell_window_->window_type_is_panel())
+  if (!app_window_->window_type_is_panel())
     return false;
 #if defined(USE_ASH)
   return !ash::wm::GetWindowState(window_->GetNativeWindow())->panel_attached();
@@ -919,13 +914,29 @@ void NativeAppWindowViews::UpdateWindowTitle() {
   window_->UpdateWindowTitle();
 }
 
+void NativeAppWindowViews::UpdateBadgeIcon() {
+  const gfx::Image* icon = NULL;
+  if (!app_window_->badge_icon().IsEmpty()) {
+    icon = &app_window_->badge_icon();
+    // chrome::DrawTaskbarDecoration can do interesting things with non-square
+    // bitmaps.
+    // TODO(benwells): Refactor chrome::DrawTaskbarDecoration to not be avatar
+    // specific, and lift this restriction.
+    if (icon->Width() != icon->Height()) {
+      LOG(ERROR) << "Attempt to set a non-square badge; request ignored.";
+      return;
+    }
+  }
+  chrome::DrawTaskbarDecoration(GetNativeWindow(), icon);
+}
+
 void NativeAppWindowViews::UpdateDraggableRegions(
     const std::vector<extensions::DraggableRegion>& regions) {
   // Draggable region is not supported for non-frameless window.
   if (!frameless_)
     return;
 
-  draggable_region_.reset(ShellWindow::RawDraggableRegionsToSkRegion(regions));
+  draggable_region_.reset(AppWindow::RawDraggableRegionsToSkRegion(regions));
   OnViewWasResized();
 }
 
@@ -941,13 +952,13 @@ void NativeAppWindowViews::UpdateShape(scoped_ptr<SkRegion> region) {
   if (shape_) {
     window_->SetShape(new SkRegion(*shape_));
     if (!had_shape) {
-      native_window->set_event_targeter(scoped_ptr<ui::EventTargeter>(
+      native_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
           new ShapedAppWindowTargeter(native_window, this)));
     }
   } else {
     window_->SetShape(NULL);
     if (had_shape)
-      native_window->set_event_targeter(scoped_ptr<ui::EventTargeter>());
+      native_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>());
   }
 }