app_activity.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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 "athena/content/app_activity.h"
6
7#include "athena/activity/public/activity_manager.h"
8#include "athena/content/app_activity_registry.h"
9#include "athena/content/content_proxy.h"
10#include "athena/content/public/app_registry.h"
11#include "athena/wm/public/window_list_provider.h"
12#include "athena/wm/public/window_manager.h"
13#include "content/public/browser/web_contents.h"
14#include "extensions/browser/app_window/app_window.h"
15#include "ui/aura/window.h"
16#include "ui/views/controls/webview/webview.h"
17#include "ui/views/widget/widget.h"
18
19namespace athena {
20
21// TODO(mukai): specifies the same accelerators of WebActivity.
22AppActivity::AppActivity(extensions::AppWindow* app_window,
23                         views::WebView* web_view)
24    : app_id_(app_window->extension_id()),
25      web_view_(web_view),
26      current_state_(ACTIVITY_UNLOADED),
27      app_activity_registry_(NULL) {
28  DCHECK_EQ(app_window->web_contents(), web_view->GetWebContents());
29  Observe(app_window->web_contents());
30}
31
32scoped_ptr<ContentProxy> AppActivity::GetContentProxy() {
33  // Note: After this call, the content is still valid because the contents
34  // destruction will destroy this |AppActivity| object.
35  if (content_proxy_.get())
36    content_proxy_->OnPreContentDestroyed();
37  return content_proxy_.Pass();
38}
39
40ActivityViewModel* AppActivity::GetActivityViewModel() {
41  return this;
42}
43
44void AppActivity::SetCurrentState(Activity::ActivityState state) {
45  DCHECK_NE(state, current_state_);
46  ActivityState current_state = current_state_;
47  // Remember the last requested state now so that a call to GetCurrentState()
48  // returns the new state.
49  current_state_ = state;
50
51  switch (state) {
52    case ACTIVITY_VISIBLE:
53      HideContentProxy();
54      return;
55    case ACTIVITY_INVISIBLE:
56      if (current_state == ACTIVITY_VISIBLE)
57        ShowContentProxy();
58      break;
59    case ACTIVITY_BACKGROUND_LOW_PRIORITY:
60      DCHECK(ACTIVITY_VISIBLE == current_state ||
61             ACTIVITY_INVISIBLE == current_state);
62      // TODO(skuhne): Do this.
63      break;
64    case ACTIVITY_PERSISTENT:
65      DCHECK_EQ(ACTIVITY_BACKGROUND_LOW_PRIORITY, current_state);
66      // TODO(skuhne): Do this.
67      break;
68    case ACTIVITY_UNLOADED:
69      DCHECK_NE(ACTIVITY_UNLOADED, current_state);
70      // This will cause the application to shut down, close its windows and
71      // delete this object. Instead a |AppActivityProxy| will be created as
72      // place holder.
73      if (app_activity_registry_)
74        app_activity_registry_->Unload();
75      break;
76  }
77}
78
79Activity::ActivityState AppActivity::GetCurrentState() {
80  DCHECK(web_view_ || ACTIVITY_UNLOADED == current_state_);
81  return current_state_;
82}
83
84bool AppActivity::IsVisible() {
85  return web_view_ &&
86         web_view_->visible() &&
87         current_state_ != ACTIVITY_UNLOADED;
88}
89
90Activity::ActivityMediaState AppActivity::GetMediaState() {
91  // TODO(skuhne): The function GetTabMediaStateForContents(WebContents),
92  // and the AudioStreamMonitor needs to be moved from Chrome into contents to
93  // make it more modular and so that we can use it from here.
94  return Activity::ACTIVITY_MEDIA_STATE_NONE;
95}
96
97aura::Window* AppActivity::GetWindow() {
98  return !web_view_ ? NULL : web_view_->GetWidget()->GetNativeWindow();
99}
100
101content::WebContents* AppActivity::GetWebContents() {
102  return !web_view_ ? NULL : web_view_->GetWebContents();
103}
104
105void AppActivity::Init() {
106  DCHECK(app_activity_registry_);
107  Activity* app_proxy = app_activity_registry_->unloaded_activity_proxy();
108  if (app_proxy) {
109    // Note: At this time the |AppActivity| did not get registered to the
110    // |ResourceManager| - so we can move it around if needed.
111    WindowListProvider* window_list_provider =
112        WindowManager::Get()->GetWindowListProvider();
113    window_list_provider->StackWindowFrontOf(app_proxy->GetWindow(),
114                                             GetWindow());
115    Activity::Delete(app_proxy);
116    // With the removal the object, the proxy should be deleted.
117    DCHECK(!app_activity_registry_->unloaded_activity_proxy());
118  }
119}
120
121SkColor AppActivity::GetRepresentativeColor() const {
122  // TODO(sad): Compute the color from the favicon.
123  return SK_ColorGRAY;
124}
125
126base::string16 AppActivity::GetTitle() const {
127  return web_view_->GetWebContents()->GetTitle();
128}
129
130gfx::ImageSkia AppActivity::GetIcon() const {
131  return gfx::ImageSkia();
132}
133
134bool AppActivity::UsesFrame() const {
135  return false;
136}
137
138views::Widget* AppActivity::CreateWidget() {
139  // Make sure the content gets properly shown.
140  if (current_state_ == ACTIVITY_VISIBLE) {
141    HideContentProxy();
142  } else if (current_state_ == ACTIVITY_INVISIBLE) {
143    ShowContentProxy();
144  } else {
145    // If not previously specified, we change the state now to invisible..
146    SetCurrentState(ACTIVITY_INVISIBLE);
147  }
148  RegisterActivity();
149  return web_view_->GetWidget();
150}
151
152views::View* AppActivity::GetContentsView() {
153  return web_view_;
154}
155
156gfx::ImageSkia AppActivity::GetOverviewModeImage() {
157  if (content_proxy_.get())
158    return content_proxy_->GetContentImage();
159  return gfx::ImageSkia();
160}
161
162void AppActivity::PrepareContentsForOverview() {
163  // Turn on fast resizing to avoid re-laying out the web contents when
164  // entering / exiting overview mode and the content is visible.
165  if (!content_proxy_.get())
166    web_view_->SetFastResize(true);
167}
168
169void AppActivity::ResetContentsView() {
170  // Turn on fast resizing to avoid re-laying out the web contents when
171  // entering / exiting overview mode and the content is visible.
172  if (!content_proxy_.get()) {
173    web_view_->SetFastResize(false);
174    web_view_->Layout();
175  }
176}
177
178AppActivity::AppActivity(const std::string& app_id)
179    : app_id_(app_id),
180      web_view_(NULL),
181      current_state_(ACTIVITY_UNLOADED),
182      app_activity_registry_(NULL) {
183}
184
185AppActivity::~AppActivity() {
186  // If this activity is registered, we unregister it now.
187  if (app_activity_registry_)
188    app_activity_registry_->UnregisterAppActivity(this);
189}
190
191void AppActivity::TitleWasSet(content::NavigationEntry* entry,
192                              bool explicit_set) {
193  ActivityManager::Get()->UpdateActivity(this);
194}
195
196void AppActivity::DidUpdateFaviconURL(
197    const std::vector<content::FaviconURL>& candidates) {
198  ActivityManager::Get()->UpdateActivity(this);
199}
200
201// Register an |activity| with an application.
202// Note: This should only get called once for an |app_window| of the
203// |activity|.
204void AppActivity::RegisterActivity() {
205  content::WebContents* web_contents = web_view_->GetWebContents();
206  AppRegistry* app_registry = AppRegistry::Get();
207  // Get the application's registry.
208  app_activity_registry_ = app_registry->GetAppActivityRegistry(
209      app_id_, web_contents->GetBrowserContext());
210  DCHECK(app_activity_registry_);
211  // Register the activity.
212  app_activity_registry_->RegisterAppActivity(this);
213}
214
215void AppActivity::HideContentProxy() {
216  content_proxy_.reset();
217}
218
219void AppActivity::ShowContentProxy() {
220  if (!content_proxy_.get() && web_view_)
221    content_proxy_.reset(new ContentProxy(web_view_, this));
222}
223
224}  // namespace athena
225