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.
5 #include "athena/content/app_activity.h"
7 #include "athena/activity/public/activity_manager.h"
8 #include "athena/activity/public/activity_view.h"
9 #include "athena/content/app_activity_registry.h"
10 #include "athena/content/content_proxy.h"
11 #include "athena/content/media_utils.h"
12 #include "athena/content/public/app_registry.h"
13 #include "athena/wm/public/window_list_provider.h"
14 #include "athena/wm/public/window_manager.h"
15 #include "content/public/browser/web_contents.h"
16 #include "ui/aura/window.h"
17 #include "ui/views/controls/webview/webview.h"
18 #include "ui/views/widget/widget.h"
19 #include "ui/wm/core/window_util.h"
23 // TODO(mukai): specifies the same accelerators of WebActivity.
24 AppActivity::AppActivity(const std::string
& app_id
, views::WebView
* web_view
)
27 current_state_(ACTIVITY_UNLOADED
),
28 app_activity_registry_(nullptr),
29 activity_view_(nullptr) {
30 Observe(web_view
->GetWebContents());
33 scoped_ptr
<ContentProxy
> AppActivity::GetContentProxy() {
34 // Note: After this call, the content is still valid because the contents
35 // destruction will destroy this |AppActivity| object.
36 if (content_proxy_
.get())
37 content_proxy_
->OnPreContentDestroyed();
38 return content_proxy_
.Pass();
41 ActivityViewModel
* AppActivity::GetActivityViewModel() {
45 void AppActivity::SetCurrentState(Activity::ActivityState state
) {
46 DCHECK_NE(state
, current_state_
);
47 ActivityState current_state
= current_state_
;
48 // Remember the last requested state now so that a call to GetCurrentState()
49 // returns the new state.
50 current_state_
= state
;
53 case ACTIVITY_VISIBLE
:
56 case ACTIVITY_INVISIBLE
:
57 if (current_state
== ACTIVITY_VISIBLE
)
60 case ACTIVITY_BACKGROUND_LOW_PRIORITY
:
61 DCHECK(ACTIVITY_VISIBLE
== current_state
||
62 ACTIVITY_INVISIBLE
== current_state
);
63 // TODO(skuhne): Do this.
65 case ACTIVITY_PERSISTENT
:
66 DCHECK_EQ(ACTIVITY_BACKGROUND_LOW_PRIORITY
, current_state
);
67 // TODO(skuhne): Do this.
69 case ACTIVITY_UNLOADED
:
70 DCHECK_NE(ACTIVITY_UNLOADED
, current_state
);
71 // This will cause the application to shut down, close its windows and
72 // delete this object. Instead a |AppActivityProxy| will be created as
74 if (app_activity_registry_
)
75 app_activity_registry_
->Unload();
80 Activity::ActivityState
AppActivity::GetCurrentState() {
81 DCHECK(web_view_
|| ACTIVITY_UNLOADED
== current_state_
);
82 return current_state_
;
85 bool AppActivity::IsVisible() {
87 web_view_
->visible() &&
88 current_state_
!= ACTIVITY_UNLOADED
;
91 Activity::ActivityMediaState
AppActivity::GetMediaState() {
92 return current_state_
== ACTIVITY_UNLOADED
?
93 Activity::ACTIVITY_MEDIA_STATE_NONE
:
94 GetActivityMediaState(GetWebContents());
97 aura::Window
* AppActivity::GetWindow() {
98 return web_view_
&& web_view_
->GetWidget()
99 ? web_view_
->GetWidget()->GetNativeWindow()
103 content::WebContents
* AppActivity::GetWebContents() {
104 return !web_view_
? nullptr : web_view_
->GetWebContents();
107 void AppActivity::Init() {
108 // Before we remove the proxy, we have to register the activity and
109 // initialize its to move it to the proper activity list location.
112 DCHECK(app_activity_registry_
);
113 Activity
* app_proxy
= app_activity_registry_
->unloaded_activity_proxy();
115 // Note: At this time the |AppActivity| did not get registered to the
116 // |ResourceManager| - so we can move it around if needed.
117 WindowListProvider
* window_list_provider
=
118 WindowManager::Get()->GetWindowListProvider();
119 // TODO(skuhne): After the decision is made how we want to handle visibility
120 // transitions (issue 421680) this code might change.
121 // If the proxy was the active window, its deletion will cause a window
122 // reordering since the next activatable window in line will move up to the
123 // front. Since the application window is still hidden at this time, it is
124 // not yet activatable and the window behind it will move to the front.
125 if (wm::IsActiveWindow(app_proxy
->GetWindow())) {
126 // Delete the proxy window first and then move the new window to the top
127 // of the stack, replacing the proxy window. Note that by deleting the
128 // proxy the activation will change to the next (activatable) object and
129 // thus we have to move the window in front at the end.
130 Activity::Delete(app_proxy
);
131 if (GetWindow() != window_list_provider
->GetWindowList().back()) {
132 window_list_provider
->StackWindowFrontOf(
134 window_list_provider
->GetWindowList().back());
137 // The app window goes in front of the proxy window (we need to first
138 // place the window before we can delete it).
139 window_list_provider
->StackWindowFrontOf(GetWindow(),
140 app_proxy
->GetWindow());
141 Activity::Delete(app_proxy
);
143 // The proxy should now be deleted.
144 DCHECK(!app_activity_registry_
->unloaded_activity_proxy());
147 // Make sure the content gets properly shown.
148 if (current_state_
== ACTIVITY_VISIBLE
) {
150 } else if (current_state_
== ACTIVITY_INVISIBLE
) {
153 // If not previously specified, we change the state now to invisible..
154 SetCurrentState(ACTIVITY_INVISIBLE
);
158 SkColor
AppActivity::GetRepresentativeColor() const {
159 // TODO(sad): Compute the color from the favicon.
163 base::string16
AppActivity::GetTitle() const {
164 return web_view_
->GetWebContents()->GetTitle();
167 gfx::ImageSkia
AppActivity::GetIcon() const {
168 return gfx::ImageSkia();
171 void AppActivity::SetActivityView(ActivityView
* view
) {
172 DCHECK(!activity_view_
);
173 activity_view_
= view
;
176 bool AppActivity::UsesFrame() const {
180 views::View
* AppActivity::GetContentsView() {
184 gfx::ImageSkia
AppActivity::GetOverviewModeImage() {
185 if (content_proxy_
.get())
186 return content_proxy_
->GetContentImage();
187 return gfx::ImageSkia();
190 void AppActivity::PrepareContentsForOverview() {
191 // Turn on fast resizing to avoid re-laying out the web contents when
192 // entering / exiting overview mode and the content is visible.
193 if (!content_proxy_
.get())
194 web_view_
->SetFastResize(true);
197 void AppActivity::ResetContentsView() {
198 // Turn on fast resizing to avoid re-laying out the web contents when
199 // entering / exiting overview mode and the content is visible.
200 if (!content_proxy_
.get()) {
201 web_view_
->SetFastResize(false);
206 AppActivity::AppActivity(const std::string
& app_id
)
209 current_state_(ACTIVITY_UNLOADED
),
210 app_activity_registry_(nullptr),
211 activity_view_(nullptr) {
214 AppActivity::~AppActivity() {
215 // If this activity is registered, we unregister it now.
216 if (app_activity_registry_
)
217 app_activity_registry_
->UnregisterAppActivity(this);
220 void AppActivity::TitleWasSet(content::NavigationEntry
* entry
,
223 activity_view_
->UpdateTitle();
226 void AppActivity::DidUpdateFaviconURL(
227 const std::vector
<content::FaviconURL
>& candidates
) {
229 activity_view_
->UpdateIcon();
232 // Register an |activity| with an application.
233 // Note: This should only get called once for an |app_window| of the
235 void AppActivity::RegisterActivity() {
236 content::WebContents
* web_contents
= web_view_
->GetWebContents();
237 AppRegistry
* app_registry
= AppRegistry::Get();
238 // Get the application's registry.
239 app_activity_registry_
= app_registry
->GetAppActivityRegistry(
240 app_id_
, web_contents
->GetBrowserContext());
241 DCHECK(app_activity_registry_
);
242 // Register the activity.
243 app_activity_registry_
->RegisterAppActivity(this);
246 void AppActivity::HideContentProxy() {
247 content_proxy_
.reset();
250 void AppActivity::ShowContentProxy() {
251 if (!content_proxy_
.get() && web_view_
)
252 content_proxy_
.reset(new ContentProxy(web_view_
));
255 } // namespace athena