Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / app_list_shower_views.cc
1 // Copyright 2014 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/app_list/app_list_shower_views.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "chrome/browser/apps/scoped_keep_alive.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/app_list/app_list_shower_delegate.h"
12 #include "chrome/browser/ui/app_list/app_list_view_delegate.h"
13 #include "ui/app_list/views/app_list_view.h"
14 #include "ui/gfx/geometry/point.h"
15 #include "ui/gfx/screen.h"
16
17 AppListShower::AppListShower(AppListShowerDelegate* delegate)
18     : delegate_(delegate),
19       profile_(NULL),
20       app_list_(NULL),
21       window_icon_updated_(false) {
22 }
23
24 AppListShower::~AppListShower() {
25 }
26
27 void AppListShower::ShowForProfile(Profile* requested_profile) {
28   // If the app list is already displaying |profile| just activate it (in case
29   // we have lost focus).
30   if (IsAppListVisible() && (requested_profile == profile_)) {
31     Show();
32     return;
33   }
34
35   if (!HasView()) {
36     CreateViewForProfile(requested_profile);
37   } else if (requested_profile != profile_) {
38     profile_ = requested_profile;
39     UpdateViewForNewProfile();
40   }
41
42   keep_alive_.reset(new ScopedKeepAlive);
43   if (!IsAppListVisible())
44     delegate_->MoveNearCursor(app_list_);
45   Show();
46 }
47
48 gfx::NativeWindow AppListShower::GetWindow() {
49   if (!IsAppListVisible())
50     return NULL;
51   return app_list_->GetWidget()->GetNativeWindow();
52 }
53
54 void AppListShower::CreateViewForProfile(Profile* requested_profile) {
55   profile_ = requested_profile;
56   app_list_ = MakeViewForCurrentProfile();
57   delegate_->OnViewCreated();
58 }
59
60 void AppListShower::DismissAppList() {
61   if (HasView()) {
62     Hide();
63     delegate_->OnViewDismissed();
64     // This can be reached by pressing the dismiss accelerator. To prevent
65     // events from being processed with a destroyed dispatcher, delay the reset
66     // of the keep alive.
67     ResetKeepAliveSoon();
68   }
69 }
70
71 void AppListShower::HandleViewBeingDestroyed() {
72   app_list_ = NULL;
73   profile_ = NULL;
74
75   // We may end up here as the result of the OS deleting the AppList's
76   // widget (WidgetObserver::OnWidgetDestroyed). If this happens and there
77   // are no browsers around then deleting the keep alive will result in
78   // deleting the Widget again (by way of CloseAllSecondaryWidgets). When
79   // the stack unravels we end up back in the Widget that was deleted and
80   // crash. By delaying deletion of the keep alive we ensure the Widget has
81   // correctly been destroyed before ending the keep alive so that
82   // CloseAllSecondaryWidgets() won't attempt to delete the AppList's Widget
83   // again.
84   ResetKeepAliveSoon();
85 }
86
87 bool AppListShower::IsAppListVisible() const {
88   return app_list_ && app_list_->GetWidget()->IsVisible();
89 }
90
91 void AppListShower::WarmupForProfile(Profile* profile) {
92   DCHECK(!profile_);
93   CreateViewForProfile(profile);
94   app_list_->Prerender();
95 }
96
97 bool AppListShower::HasView() const {
98   return !!app_list_;
99 }
100
101 app_list::AppListView* AppListShower::MakeViewForCurrentProfile() {
102   // The app list view manages its own lifetime.
103   app_list::AppListView* view =
104       new app_list::AppListView(delegate_->GetViewDelegateForCreate());
105   gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
106   view->InitAsBubbleAtFixedLocation(NULL,
107                                     0,
108                                     cursor,
109                                     views::BubbleBorder::FLOAT,
110                                     false /* border_accepts_events */);
111   return view;
112 }
113
114 void AppListShower::UpdateViewForNewProfile() {
115   app_list_->SetProfileByPath(profile_->GetPath());
116 }
117
118 void AppListShower::Show() {
119   app_list_->GetWidget()->Show();
120   if (!window_icon_updated_) {
121     app_list_->GetWidget()->GetTopLevelWidget()->UpdateWindowIcon();
122     window_icon_updated_ = true;
123   }
124   app_list_->GetWidget()->Activate();
125 }
126
127 void AppListShower::Hide() {
128   app_list_->GetWidget()->Hide();
129 }
130
131 void AppListShower::ResetKeepAliveSoon() {
132   if (base::MessageLoop::current()) {  // NULL in tests.
133     base::MessageLoop::current()->PostTask(
134         FROM_HERE,
135         base::Bind(&AppListShower::ResetKeepAlive, base::Unretained(this)));
136     return;
137   }
138   ResetKeepAlive();
139 }
140
141 void AppListShower::ResetKeepAlive() {
142   keep_alive_.reset();
143 }