| // 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/test/test_app_window_icon_observer.h" |
| |
| #include "base/md5.h" |
| #include "base/run_loop.h" |
| #include "extensions/browser/app_window/app_window.h" |
| #include "ui/aura/client/aura_constants.h" |
| #include "ui/aura/window.h" |
| |
| TestAppWindowIconObserver::TestAppWindowIconObserver( |
| content::BrowserContext* context) |
| : context_(context) { |
| extensions::AppWindowRegistry::Get(context_)->AddObserver(this); |
| } |
| |
| TestAppWindowIconObserver::~TestAppWindowIconObserver() { |
| extensions::AppWindowRegistry::Get(context_)->RemoveObserver(this); |
| for (aura::Window* window : windows_) |
| window->RemoveObserver(this); |
| } |
| |
| void TestAppWindowIconObserver::WaitForIconUpdate() { |
| WaitForIconUpdates(1); |
| } |
| |
| void TestAppWindowIconObserver::WaitForIconUpdates(int updates) { |
| base::RunLoop run_loop; |
| expected_icon_updates_ = updates + icon_updates_; |
| icon_updated_callback_ = run_loop.QuitClosure(); |
| run_loop.Run(); |
| base::RunLoop().RunUntilIdle(); |
| DCHECK_EQ(expected_icon_updates_, icon_updates_); |
| } |
| |
| void TestAppWindowIconObserver::OnAppWindowAdded( |
| extensions::AppWindow* app_window) { |
| aura::Window* window = app_window->GetNativeWindow(); |
| window->AddObserver(this); |
| windows_.push_back(window); |
| // Handle the case where the app icon is already set prior to this callback. |
| // If it is set, handle the icon update immediately. |
| OnWindowPropertyChanged(window, aura::client::kAppIconKey, 0); |
| } |
| |
| void TestAppWindowIconObserver::OnAppWindowRemoved( |
| extensions::AppWindow* app_window) { |
| aura::Window* window = app_window->GetNativeWindow(); |
| if (window) { |
| windows_.erase(std::find(windows_.begin(), windows_.end(), window)); |
| window->RemoveObserver(this); |
| } |
| } |
| |
| void TestAppWindowIconObserver::OnWindowPropertyChanged(aura::Window* window, |
| const void* key, |
| intptr_t old) { |
| if (key != aura::client::kAppIconKey) |
| return; |
| |
| std::string app_icon_hash; |
| const gfx::ImageSkia* image = window->GetProperty(aura::client::kAppIconKey); |
| last_app_icon_ = image ? *image : gfx::ImageSkia(); |
| |
| if (image && !image->isNull()) { |
| const SkBitmap* bitmap = image->bitmap(); |
| |
| // The window icon property changes more frequently than the image itself |
| // leading to test flakiness. Just record instances where the image actually |
| // changes. |
| base::MD5Context ctx; |
| base::MD5Init(&ctx); |
| const size_t row_width = bitmap->bytesPerPixel() * bitmap->width(); |
| for (int y = 0; y < bitmap->height(); ++y) { |
| base::MD5Update( |
| &ctx, |
| base::StringPiece( |
| reinterpret_cast<const char*>(bitmap->getAddr(0, y)), row_width)); |
| } |
| base::MD5Digest digest; |
| base::MD5Final(&digest, &ctx); |
| app_icon_hash = base::MD5DigestToBase16(digest); |
| } |
| |
| if (app_icon_hash == last_app_icon_hash_map_[window]) |
| return; |
| |
| last_app_icon_hash_map_[window] = app_icon_hash; |
| ++icon_updates_; |
| if (icon_updates_ == expected_icon_updates_ && |
| !icon_updated_callback_.is_null()) { |
| base::ResetAndReturn(&icon_updated_callback_).Run(); |
| } |
| } |