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