Index: chrome/browser/ui/ash/launcher/arc_app_window.cc |
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window.cc b/chrome/browser/ui/ash/launcher/arc_app_window.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..10d5a6affab02487aff6bea9a486f7020f269956 |
--- /dev/null |
+++ b/chrome/browser/ui/ash/launcher/arc_app_window.cc |
@@ -0,0 +1,227 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/ui/ash/launcher/arc_app_window.h" |
+ |
+#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" |
+#include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h" |
+#include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller.h" |
+#include "components/exo/shell_surface.h" |
+#include "extensions/common/constants.h" |
+#include "ui/aura/window.h" |
+#include "ui/gfx/codec/png_codec.h" |
+#include "ui/gfx/image/image_skia_operations.h" |
+#include "ui/gfx/image/image_skia_source.h" |
+#include "ui/views/widget/widget.h" |
+ |
+namespace { |
+ |
+// Set to true for unit tests to avoid IPC icon decoding. |
+bool disable_safe_icon_decoding = false; |
+ |
+// Source of the custom icon of ARC app window. It takes reference bitmap and |
+// resizes to required scale factor on demand. |
+class CustomIconSource : public gfx::ImageSkiaSource { |
+ public: |
+ explicit CustomIconSource(const SkBitmap& base_image) |
+ : base_image_(base_image) {} |
+ ~CustomIconSource() override = default; |
+ |
+ private: |
+ // gfx::ImageSkiaSource overrides: |
+ gfx::ImageSkiaRep GetImageForScale(float scale) override { |
+ const gfx::Size target_pixel_size = |
+ gfx::ScaleToCeiledSize(gfx::Size(extension_misc::EXTENSION_ICON_SMALL, |
+ extension_misc::EXTENSION_ICON_SMALL), |
+ scale); |
+ |
+ const SkBitmap resized = skia::ImageOperations::Resize( |
+ base_image_, skia::ImageOperations::RESIZE_BEST, |
+ target_pixel_size.width(), target_pixel_size.height()); |
+ return gfx::ImageSkiaRep(resized, scale); |
+ } |
+ |
+ const SkBitmap base_image_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CustomIconSource); |
+}; |
+ |
+} // namespace |
+ |
+ArcAppWindow::ArcAppWindow(int task_id, |
+ const arc::ArcAppShelfId& app_shelf_id, |
+ views::Widget* widget, |
+ ArcAppWindowLauncherController* owner) |
+ : task_id_(task_id), |
+ app_shelf_id_(app_shelf_id), |
+ widget_(widget), |
+ owner_(owner) { |
+ ExtractIconFromWindow(); |
+ GetNativeWindow()->AddObserver(this); |
+} |
+ |
+ArcAppWindow::~ArcAppWindow() { |
+ ImageDecoder::Cancel(this); |
+ if (GetNativeWindow()) |
+ GetNativeWindow()->RemoveObserver(this); |
+} |
+ |
+// static |
+void ArcAppWindow::DisableSafeIconDecodingForTesting() { |
+ disable_safe_icon_decoding = true; |
+} |
+ |
+void ArcAppWindow::SetController( |
+ ArcAppWindowLauncherItemController* controller) { |
+ DCHECK(!controller_ && controller); |
+ controller_ = controller; |
+} |
+ |
+void ArcAppWindow::ResetController() { |
+ controller_ = nullptr; |
+} |
+ |
+void ArcAppWindow::SetFullscreenMode(FullScreenMode mode) { |
+ DCHECK(mode != FullScreenMode::NOT_DEFINED); |
+ fullscreen_mode_ = mode; |
+} |
+ |
+bool ArcAppWindow::IsActive() const { |
+ return widget_->IsActive() && owner_->active_task_id() == task_id_; |
+} |
+ |
+bool ArcAppWindow::IsMaximized() const { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+bool ArcAppWindow::IsMinimized() const { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+bool ArcAppWindow::IsFullscreen() const { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+gfx::NativeWindow ArcAppWindow::GetNativeWindow() const { |
+ return widget_->GetNativeWindow(); |
+} |
+ |
+gfx::Rect ArcAppWindow::GetRestoredBounds() const { |
+ NOTREACHED(); |
+ return gfx::Rect(); |
+} |
+ |
+ui::WindowShowState ArcAppWindow::GetRestoredState() const { |
+ NOTREACHED(); |
+ return ui::SHOW_STATE_NORMAL; |
+} |
+ |
+gfx::Rect ArcAppWindow::GetBounds() const { |
+ NOTREACHED(); |
+ return gfx::Rect(); |
+} |
+ |
+void ArcAppWindow::Show() { |
+ widget_->Show(); |
+} |
+ |
+void ArcAppWindow::ShowInactive() { |
+ NOTREACHED(); |
+} |
+ |
+void ArcAppWindow::Hide() { |
+ NOTREACHED(); |
+} |
+ |
+void ArcAppWindow::Close() { |
+ arc::CloseTask(task_id_); |
+} |
+ |
+void ArcAppWindow::Activate() { |
+ widget_->Activate(); |
+} |
+ |
+void ArcAppWindow::Deactivate() { |
+ NOTREACHED(); |
+} |
+ |
+void ArcAppWindow::Maximize() { |
+ NOTREACHED(); |
+} |
+ |
+void ArcAppWindow::Minimize() { |
+ widget_->Minimize(); |
+} |
+ |
+void ArcAppWindow::Restore() { |
+ NOTREACHED(); |
+} |
+ |
+void ArcAppWindow::SetBounds(const gfx::Rect& bounds) { |
+ NOTREACHED(); |
+} |
+ |
+void ArcAppWindow::FlashFrame(bool flash) { |
+ NOTREACHED(); |
+} |
+ |
+bool ArcAppWindow::IsAlwaysOnTop() const { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+void ArcAppWindow::SetAlwaysOnTop(bool always_on_top) { |
+ NOTREACHED(); |
+} |
+ |
+void ArcAppWindow::ResetIcon() { |
+ if (image_skia_.isNull()) |
+ return; |
+ image_skia_ = gfx::ImageSkia(); |
+ controller()->OnWindowChanged(this); |
+} |
+ |
+void ArcAppWindow::ExtractIconFromWindow() { |
+ ImageDecoder::Cancel(this); |
+ const std::string* unsafe_icon_data = |
+ exo::ShellSurface::GetUnsafeIconPngData(GetNativeWindow()); |
+ if (unsafe_icon_data && !unsafe_icon_data->empty()) { |
+ if (disable_safe_icon_decoding) { |
+ SkBitmap bitmap; |
+ if (gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>( |
+ &unsafe_icon_data->front()), |
+ unsafe_icon_data->length(), &bitmap)) { |
+ OnImageDecoded(bitmap); |
+ } else { |
+ OnDecodeImageFailed(); |
+ } |
+ } else { |
+ ImageDecoder::Start(this, *unsafe_icon_data); |
+ } |
+ } else { |
+ ResetIcon(); |
+ } |
+} |
+ |
+void ArcAppWindow::OnWindowPropertyChanged(aura::Window* window, |
+ const void* key, |
+ intptr_t old) { |
+ if (!exo::ShellSurface::IsUnsafeIconPngDataKey(key)) |
+ return; |
+ ExtractIconFromWindow(); |
+} |
+ |
+void ArcAppWindow::OnImageDecoded(const SkBitmap& decoded_image) { |
+ image_skia_ = gfx::ImageSkia(new CustomIconSource(decoded_image), |
+ gfx::Size(extension_misc::EXTENSION_ICON_SMALL, |
+ extension_misc::EXTENSION_ICON_SMALL)); |
+ controller()->OnWindowChanged(this); |
+} |
+ |
+void ArcAppWindow::OnDecodeImageFailed() { |
+ ResetIcon(); |
+} |