OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 "base/bind.h" | |
6 #include "base/message_loop/message_loop.h" | |
7 #include "chrome/browser/ui/app_list/app_list_shower.h" | |
8 #include "chrome/browser/ui/app_list/scoped_keep_alive.h" | |
9 | |
10 AppListShower::AppListShower(scoped_ptr<AppListFactory> factory, | |
11 AppListService* service) | |
12 : factory_(factory.Pass()), | |
13 service_(service), | |
14 profile_(NULL), | |
15 can_close_app_list_(true) { | |
16 } | |
17 | |
18 AppListShower::~AppListShower() { | |
19 } | |
20 | |
21 void AppListShower::ShowForProfile(Profile* requested_profile) { | |
22 // If the app list is already displaying |profile| just activate it (in case | |
23 // we have lost focus). | |
24 if (IsAppListVisible() && (requested_profile == profile_)) { | |
25 app_list_->Show(); | |
26 return; | |
27 } | |
28 | |
29 if (!app_list_) { | |
30 CreateViewForProfile(requested_profile); | |
31 } else if (requested_profile != profile_) { | |
32 profile_ = requested_profile; | |
33 app_list_->SetProfile(requested_profile); | |
34 } | |
35 | |
36 keep_alive_.reset(new ScopedKeepAlive); | |
37 if (!IsAppListVisible()) | |
38 app_list_->MoveNearCursor(); | |
39 app_list_->Show(); | |
40 } | |
41 | |
42 gfx::NativeWindow AppListShower::GetWindow() { | |
43 if (!IsAppListVisible()) | |
44 return NULL; | |
45 return app_list_->GetWindow(); | |
46 } | |
47 | |
48 void AppListShower::CreateViewForProfile(Profile* requested_profile) { | |
49 profile_ = requested_profile; | |
50 app_list_.reset(factory_->CreateAppList( | |
51 profile_, | |
52 service_, | |
53 base::Bind(&AppListShower::DismissAppList, base::Unretained(this)))); | |
54 } | |
55 | |
56 void AppListShower::DismissAppList() { | |
57 if (app_list_ && can_close_app_list_) { | |
58 app_list_->Hide(); | |
59 keep_alive_.reset(); | |
60 } | |
61 } | |
62 | |
63 void AppListShower::HandleViewBeingDestroyed() { | |
64 app_list_.reset(); | |
65 profile_ = NULL; | |
66 can_close_app_list_ = true; | |
67 | |
68 // We may end up here as the result of the OS deleting the AppList's | |
69 // widget (WidgetObserver::OnWidgetDestroyed). If this happens and there | |
70 // are no browsers around then deleting the keep alive will result in | |
71 // deleting the Widget again (by way of CloseAllSecondaryWidgets). When | |
72 // the stack unravels we end up back in the Widget that was deleted and | |
73 // crash. By delaying deletion of the keep alive we ensure the Widget has | |
74 // correctly been destroyed before ending the keep alive so that | |
75 // CloseAllSecondaryWidgets() won't attempt to delete the AppList's Widget | |
76 // again. | |
77 if (base::MessageLoop::current()) { // NULL in tests. | |
78 base::MessageLoop::current()->PostTask( | |
79 FROM_HERE, | |
80 base::Bind(&AppListShower::ResetKeepAlive, base::Unretained(this))); | |
81 return; | |
82 } | |
83 keep_alive_.reset(); | |
84 } | |
85 | |
86 bool AppListShower::IsAppListVisible() const { | |
87 return app_list_ && app_list_->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 void AppListShower::ResetKeepAlive() { | |
101 keep_alive_.reset(); | |
102 } | |
OLD | NEW |