OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h" |
| 6 |
| 7 #include "ash/shelf/shelf_util.h" |
| 8 #include "ash/wm/window_util.h" |
| 9 #include "base/bind.h" |
| 10 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" |
| 11 #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_item_controller
.h" |
| 12 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
| 13 #include "components/arc/arc_bridge_service.h" |
| 14 #include "components/exo/shell_surface.h" |
| 15 #include "ui/aura/env.h" |
| 16 #include "ui/base/base_window.h" |
| 17 #include "ui/views/widget/widget.h" |
| 18 |
| 19 class ArcAppWindowLauncherController::AppWindow : public ui::BaseWindow { |
| 20 public: |
| 21 AppWindow(int task_id, views::Widget* widget) |
| 22 : task_id_(task_id), widget_(widget) {} |
| 23 ~AppWindow() {} |
| 24 |
| 25 void SetController(ArcAppWindowLauncherItemController* controller) { |
| 26 DCHECK(!controller_ && controller); |
| 27 controller_ = controller; |
| 28 } |
| 29 |
| 30 int task_id() const { return task_id_; } |
| 31 |
| 32 ArcAppWindowLauncherItemController* controller() { return controller_; } |
| 33 |
| 34 // ui::BaseWindow: |
| 35 bool IsActive() const override { return widget_->IsActive(); } |
| 36 |
| 37 bool IsMaximized() const override { return widget_->IsMaximized(); } |
| 38 |
| 39 bool IsMinimized() const override { return widget_->IsMinimized(); } |
| 40 |
| 41 bool IsFullscreen() const override { return widget_->IsFullscreen(); } |
| 42 |
| 43 gfx::NativeWindow GetNativeWindow() const override { |
| 44 return widget_->GetNativeWindow(); |
| 45 } |
| 46 |
| 47 gfx::Rect GetRestoredBounds() const override { |
| 48 return widget_->GetRestoredBounds(); |
| 49 } |
| 50 |
| 51 ui::WindowShowState GetRestoredState() const override { |
| 52 // Stub implementation. See also ChromeNativeAppWindowViews. |
| 53 if (IsMaximized()) |
| 54 return ui::SHOW_STATE_MAXIMIZED; |
| 55 if (IsFullscreen()) |
| 56 return ui::SHOW_STATE_FULLSCREEN; |
| 57 return ui::SHOW_STATE_NORMAL; |
| 58 } |
| 59 |
| 60 gfx::Rect GetBounds() const override { |
| 61 return widget_->GetWindowBoundsInScreen(); |
| 62 } |
| 63 |
| 64 void Show() override { |
| 65 if (widget_->IsVisible()) { |
| 66 widget_->Activate(); |
| 67 return; |
| 68 } |
| 69 widget_->Show(); |
| 70 } |
| 71 |
| 72 void ShowInactive() override { |
| 73 if (widget_->IsVisible()) |
| 74 return; |
| 75 |
| 76 widget_->ShowInactive(); |
| 77 } |
| 78 |
| 79 void Hide() override { widget_->Hide(); } |
| 80 |
| 81 void Close() override { widget_->Close(); } |
| 82 |
| 83 void Activate() override { widget_->Activate(); } |
| 84 |
| 85 void Deactivate() override { widget_->Deactivate(); } |
| 86 |
| 87 void Maximize() override { widget_->Maximize(); } |
| 88 |
| 89 void Minimize() override { widget_->Minimize(); } |
| 90 |
| 91 void Restore() override { widget_->Restore(); } |
| 92 |
| 93 void SetBounds(const gfx::Rect& bounds) override { |
| 94 widget_->SetBounds(bounds); |
| 95 } |
| 96 |
| 97 void FlashFrame(bool flash) override { widget_->FlashFrame(flash); } |
| 98 |
| 99 bool IsAlwaysOnTop() const override { return widget_->IsAlwaysOnTop(); } |
| 100 |
| 101 void SetAlwaysOnTop(bool always_on_top) override { |
| 102 widget_->SetAlwaysOnTop(always_on_top); |
| 103 } |
| 104 |
| 105 private: |
| 106 int task_id_; |
| 107 // Unowned pointers |
| 108 views::Widget* widget_; |
| 109 ArcAppWindowLauncherItemController* controller_ = nullptr; |
| 110 |
| 111 DISALLOW_COPY_AND_ASSIGN(AppWindow); |
| 112 }; |
| 113 |
| 114 ArcAppWindowLauncherController::ArcAppWindowLauncherController( |
| 115 ChromeLauncherController* owner) |
| 116 : AppWindowLauncherController(owner), |
| 117 observed_windows_(this), |
| 118 weak_ptr_factory_(this) { |
| 119 aura::Env* env = aura::Env::GetInstanceDontCreate(); |
| 120 if (env) |
| 121 env->AddObserver(this); |
| 122 } |
| 123 |
| 124 ArcAppWindowLauncherController::~ArcAppWindowLauncherController() { |
| 125 aura::Env* env = aura::Env::GetInstanceDontCreate(); |
| 126 if (env) |
| 127 env->RemoveObserver(this); |
| 128 } |
| 129 |
| 130 void ArcAppWindowLauncherController::OnWindowInitialized(aura::Window* window) { |
| 131 DCHECK(!observed_windows_.IsObserving(window)); |
| 132 |
| 133 // Root Arc window has type WINDOW_TYPE_NORMAL. |
| 134 if (window->type() != ui::wm::WINDOW_TYPE_NORMAL) |
| 135 return; |
| 136 |
| 137 observed_windows_.Add(window); |
| 138 } |
| 139 |
| 140 void ArcAppWindowLauncherController::OnWindowPropertyChanged( |
| 141 aura::Window* window, |
| 142 const void* key, |
| 143 intptr_t old) { |
| 144 if (window_to_app_window_.find(window) != window_to_app_window_.end()) |
| 145 return; |
| 146 |
| 147 const std::string app_id = exo::ShellSurface::GetApplicationId(window); |
| 148 if (app_id.empty()) |
| 149 return; |
| 150 |
| 151 int task_id = 0; |
| 152 if (sscanf(app_id.c_str(), "org.chromium.arc.%d", &task_id) != 1 || !task_id) |
| 153 return; |
| 154 |
| 155 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); |
| 156 DCHECK(widget); |
| 157 window_to_app_window_[window].reset(new AppWindow(task_id, widget)); |
| 158 |
| 159 arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); |
| 160 if (!bridge_service) { |
| 161 NOTREACHED(); |
| 162 return; |
| 163 } |
| 164 |
| 165 arc::AppInstance* app_instance = bridge_service->app_instance(); |
| 166 if (!app_instance) { |
| 167 VLOG(2) << "Request to resolve task when bridge service is not ready."; |
| 168 return; |
| 169 } |
| 170 |
| 171 // Resolve information about task. |
| 172 app_instance->GetTaskInfo( |
| 173 task_id, base::Bind(&ArcAppWindowLauncherController::OnGetTaskInfo, |
| 174 weak_ptr_factory_.GetWeakPtr(), task_id)); |
| 175 } |
| 176 |
| 177 void ArcAppWindowLauncherController::OnWindowDestroying(aura::Window* window) { |
| 178 DCHECK(observed_windows_.IsObserving(window)); |
| 179 observed_windows_.Remove(window); |
| 180 |
| 181 WindowToAppWindow::iterator it = window_to_app_window_.find(window); |
| 182 if (it == window_to_app_window_.end()) |
| 183 return; |
| 184 |
| 185 ArcAppWindowLauncherItemController* controller = it->second->controller(); |
| 186 if (controller) { |
| 187 const std::string app_id = controller->app_id(); |
| 188 controller->RemoveWindowForNativeWindow(window); |
| 189 if (!controller->window_count()) { |
| 190 ash::ShelfID shelf_id = ash::GetShelfIDForWindow(window); |
| 191 DCHECK(shelf_id); |
| 192 owner()->CloseLauncherItem(shelf_id); |
| 193 AppControllerMap::iterator it2 = app_controller_map_.find(app_id); |
| 194 DCHECK(it2 != app_controller_map_.end()); |
| 195 app_controller_map_.erase(it2); |
| 196 } |
| 197 } |
| 198 window_to_app_window_.erase(it); |
| 199 } |
| 200 |
| 201 ArcAppWindowLauncherController::AppWindow* |
| 202 ArcAppWindowLauncherController::GetAppWindowForTask(int task_id) { |
| 203 for (auto& it : window_to_app_window_) { |
| 204 if (it.second->task_id() == task_id) |
| 205 return it.second.get(); |
| 206 } |
| 207 return nullptr; |
| 208 } |
| 209 |
| 210 void ArcAppWindowLauncherController::OnGetTaskInfo(int task_id, |
| 211 mojo::String package_name, |
| 212 mojo::String activity_name) { |
| 213 if (package_name.get().empty() || activity_name.get().empty()) |
| 214 return; |
| 215 |
| 216 AppWindow* app_window = GetAppWindowForTask(task_id); |
| 217 if (!app_window) |
| 218 return; |
| 219 |
| 220 DCHECK(app_window && !app_window->controller()); |
| 221 ash::ShelfItemStatus status = |
| 222 ash::wm::IsActiveWindow(app_window->GetNativeWindow()) |
| 223 ? ash::STATUS_ACTIVE |
| 224 : ash::STATUS_RUNNING; |
| 225 |
| 226 const std::string app_id = |
| 227 ArcAppListPrefs::GetAppId(package_name, activity_name); |
| 228 |
| 229 ArcAppWindowLauncherItemController* controller; |
| 230 AppControllerMap::iterator it = app_controller_map_.find(app_id); |
| 231 ash::ShelfID shelf_id = 0; |
| 232 if (it != app_controller_map_.end()) { |
| 233 controller = it->second; |
| 234 DCHECK(controller->app_id() == app_id); |
| 235 shelf_id = controller->shelf_id(); |
| 236 controller->AddWindow(app_window); |
| 237 } else { |
| 238 controller = new ArcAppWindowLauncherItemController(app_id, owner()); |
| 239 controller->AddWindow(app_window); |
| 240 shelf_id = owner()->GetShelfIDForAppID(app_id); |
| 241 if (shelf_id == 0) |
| 242 shelf_id = owner()->CreateAppLauncherItem(controller, app_id, status); |
| 243 else |
| 244 owner()->SetItemController(shelf_id, controller); |
| 245 app_controller_map_[app_id] = controller; |
| 246 } |
| 247 app_window->SetController(controller); |
| 248 owner()->SetItemStatus(shelf_id, status); |
| 249 ash::SetShelfIDForWindow(shelf_id, app_window->GetNativeWindow()); |
| 250 } |
| 251 |
| 252 AppWindowLauncherItemController* |
| 253 ArcAppWindowLauncherController::ControllerForWindow(aura::Window* window) { |
| 254 WindowToAppWindow::iterator it = window_to_app_window_.find(window); |
| 255 if (it == window_to_app_window_.end()) |
| 256 return nullptr; |
| 257 return it->second->controller(); |
| 258 } |
OLD | NEW |