Commit b48fe9ee authored by finnur@chromium.org's avatar finnur@chromium.org

Revert 291221 "Athena: Adding basic resource management framewor..."

Reason: Failure on ASAN build bots.
https://build.chromium.org/p/chromium.memory/builders/Linux%20Chromium%20OS%20ASan%20LSan%20Tests%20(3)/builds/2854/steps/athena_unittests/logs/OneAppActivity

> Athena: Adding basic resource management framework (un-/re-loading) of V2 applications
> 
> Functionality:
> 
> The |AppRegistry| has for each running application an |AppActivityRegistry|.
> 
> The |AppActivityRegistry| knows all activities associated with the application it represents.
> It can furthermore shut the app entirely down upon resource manager request. It will then create
> an |AppActivityProxy| for the overview mode which shows a placeholder for an unloaded app. This
> placeholder can then ask the |AppActivityRegistry| to restart the application again.
> 
> A shutdown request for the application is only performed when all activities were marked for
> UNLOAD.
> 
> If there were multiple activities upon shutdown for one app, the app has to take care of
> re-creating all windows and thus re-creating all activities. Since an activity match cannot
> be performed, the |AppActivityProxy| will only be shown once and it will show in the location
> of the most recently used activity of that app. If we later on find an app which really uses
> multiple windows and it is imperative to keep the history for all of them tact & the app is
> recreating them properly, (a lot of if's) we can revisit the single |AppActivityProxy| and
> try to address it in a cleaner way, but at this time that seems rather un-useful since it is
> not known if required.
> 
> BUG=388085
> TEST=AppActivityTest.*
> 
> Review URL: https://codereview.chromium.org/477523002

TBR=skuhne@chromium.org

Review URL: https://codereview.chromium.org/497013002

Cr-Commit-Position: refs/heads/master@{#291370}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@291370 0039d316-1c4b-4281-b951-d872f2087c98
parent a9ca8d58
...@@ -9,10 +9,6 @@ ...@@ -9,10 +9,6 @@
#include "athena/athena_export.h" #include "athena/athena_export.h"
namespace aura {
class Window;
}
namespace athena { namespace athena {
class ActivityViewModel; class ActivityViewModel;
...@@ -76,10 +72,6 @@ class ATHENA_EXPORT Activity { ...@@ -76,10 +72,6 @@ class ATHENA_EXPORT Activity {
// Returns the current media state. // Returns the current media state.
virtual ActivityMediaState GetMediaState() = 0; virtual ActivityMediaState GetMediaState() = 0;
// Returns the window for the activity. This can be used to determine the
// stacking order of this activity against others.
virtual aura::Window* GetWindow() = 0;
}; };
} // namespace athena } // namespace athena
......
...@@ -115,39 +115,22 @@ ...@@ -115,39 +115,22 @@
'ATHENA_IMPLEMENTATION', 'ATHENA_IMPLEMENTATION',
], ],
'sources': [ 'sources': [
'content/app_activity.cc',
'content/app_activity.h',
'content/app_activity_proxy.cc',
'content/app_activity_proxy.h',
'content/app_activity_registry.cc',
'content/app_activity_registry.h',
'content/app_registry_impl.cc',
'content/content_activity_factory.cc',
'content/content_app_model_builder.cc',
'content/public/app_registry.h',
'content/public/content_activity_factory.h', 'content/public/content_activity_factory.h',
'content/public/content_app_model_builder.h', 'content/public/content_app_model_builder.h',
'content/public/web_contents_view_delegate_creator.h', 'content/public/web_contents_view_delegate_creator.h',
'content/content_activity_factory.cc',
'content/content_app_model_builder.cc',
'content/app_activity.h',
'content/app_activity.cc',
'content/render_view_context_menu_impl.cc', 'content/render_view_context_menu_impl.cc',
'content/render_view_context_menu_impl.h', 'content/render_view_context_menu_impl.h',
'content/web_activity.cc',
'content/web_activity.h', 'content/web_activity.h',
'content/web_activity.cc',
'content/web_contents_view_delegate_factory_impl.cc', 'content/web_contents_view_delegate_factory_impl.cc',
'virtual_keyboard/public/virtual_keyboard_manager.h', 'virtual_keyboard/public/virtual_keyboard_manager.h',
'virtual_keyboard/virtual_keyboard_manager_impl.cc', 'virtual_keyboard/virtual_keyboard_manager_impl.cc',
], ],
}, },
{
'target_name': 'athena_content_support_lib',
'type': 'static_library',
'dependencies': [
'../content/content.gyp:content_browser',
],
'sources': [
'content/delegate/app_content_control_delegate_impl.cc',
'content/public/app_content_control_delegate.h',
],
},
{ {
'target_name': 'athena_test_support', 'target_name': 'athena_test_support',
'type': 'static_library', 'type': 'static_library',
...@@ -169,7 +152,6 @@ ...@@ -169,7 +152,6 @@
'resources/athena_resources.gyp:athena_resources', 'resources/athena_resources.gyp:athena_resources',
], ],
'sources': [ 'sources': [
'content/public/app_content_control_delegate.h',
'test/athena_test_base.cc', 'test/athena_test_base.cc',
'test/athena_test_base.h', 'test/athena_test_base.h',
'test/athena_test_helper.cc', 'test/athena_test_helper.cc',
...@@ -178,7 +160,6 @@ ...@@ -178,7 +160,6 @@
'test/sample_activity.h', 'test/sample_activity.h',
'test/sample_activity_factory.cc', 'test/sample_activity_factory.cc',
'test/sample_activity_factory.h', 'test/sample_activity_factory.h',
'test/test_app_content_control_delegate_impl.cc',
'test/test_app_model_builder.cc', 'test/test_app_model_builder.cc',
'test/test_app_model_builder.h', 'test/test_app_model_builder.h',
'test/test_screen_manager_delegate.cc', 'test/test_screen_manager_delegate.cc',
...@@ -197,12 +178,11 @@ ...@@ -197,12 +178,11 @@
'resources/athena_resources.gyp:athena_pak', 'resources/athena_resources.gyp:athena_pak',
], ],
'sources': [ 'sources': [
'test/athena_unittests.cc',
'activity/activity_manager_unittest.cc', 'activity/activity_manager_unittest.cc',
'content/app_activity_unittest.cc',
'home/home_card_unittest.cc', 'home/home_card_unittest.cc',
'input/accelerator_manager_unittest.cc', 'input/accelerator_manager_unittest.cc',
'screen/screen_manager_unittest.cc', 'screen/screen_manager_unittest.cc',
'test/athena_unittests.cc',
'wm/split_view_controller_unittest.cc', 'wm/split_view_controller_unittest.cc',
'wm/window_list_provider_impl_unittest.cc', 'wm/window_list_provider_impl_unittest.cc',
'wm/window_manager_unittest.cc', 'wm/window_manager_unittest.cc',
......
skuhne@chromium.org
oshima@chromium.org
mukai@chromium.org
...@@ -5,13 +5,9 @@ ...@@ -5,13 +5,9 @@
#include "athena/content/app_activity.h" #include "athena/content/app_activity.h"
#include "athena/activity/public/activity_manager.h" #include "athena/activity/public/activity_manager.h"
#include "athena/content/app_activity_registry.h"
#include "athena/content/public/app_content_control_delegate.h"
#include "athena/content/public/app_registry.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "extensions/shell/browser/shell_app_window.h" #include "extensions/shell/browser/shell_app_window.h"
#include "ui/views/controls/webview/webview.h" #include "ui/views/controls/webview/webview.h"
#include "ui/views/widget/widget.h"
namespace athena { namespace athena {
...@@ -19,14 +15,13 @@ namespace athena { ...@@ -19,14 +15,13 @@ namespace athena {
AppActivity::AppActivity(extensions::ShellAppWindow* app_window) AppActivity::AppActivity(extensions::ShellAppWindow* app_window)
: app_window_(app_window), : app_window_(app_window),
web_view_(NULL), web_view_(NULL),
current_state_(ACTIVITY_UNLOADED), current_state_(ACTIVITY_UNLOADED) {
app_activity_registry_(NULL) { DCHECK(app_window_);
} }
AppActivity::~AppActivity() { AppActivity::~AppActivity() {
// If this activity is registered, we unregister it now. if (GetCurrentState() != ACTIVITY_UNLOADED)
if (app_activity_registry_) SetCurrentState(ACTIVITY_UNLOADED);
app_activity_registry_->UnregisterAppActivity(this);
} }
ActivityViewModel* AppActivity::GetActivityViewModel() { ActivityViewModel* AppActivity::GetActivityViewModel() {
...@@ -34,41 +29,35 @@ ActivityViewModel* AppActivity::GetActivityViewModel() { ...@@ -34,41 +29,35 @@ ActivityViewModel* AppActivity::GetActivityViewModel() {
} }
void AppActivity::SetCurrentState(Activity::ActivityState state) { void AppActivity::SetCurrentState(Activity::ActivityState state) {
ActivityState current_state = state;
// Remember the last requested state now so that a call to GetCurrentState()
// returns the new state.
current_state_ = state;
switch (state) { switch (state) {
case ACTIVITY_VISIBLE: case ACTIVITY_VISIBLE:
// Fall through (for the moment). // Fall through (for the moment).
case ACTIVITY_INVISIBLE: case ACTIVITY_INVISIBLE:
// By clearing the overview mode image we allow the content to be shown. // By clearing the overview mode image we allow the content to be shown.
overview_mode_image_ = gfx::ImageSkia(); overview_mode_image_ = gfx::ImageSkia();
// Note: A reload from the unloaded state will be performed through the // TODO(skuhne): Find out how to reload an app from the extension system.
// |AppActivityProxy| object and no further action isn't necessary here.
break; break;
case ACTIVITY_BACKGROUND_LOW_PRIORITY: case ACTIVITY_BACKGROUND_LOW_PRIORITY:
DCHECK(ACTIVITY_VISIBLE == current_state || DCHECK(ACTIVITY_VISIBLE == current_state_ ||
ACTIVITY_INVISIBLE == current_state); ACTIVITY_INVISIBLE == current_state_);
// TODO(skuhne): Do this. // TODO(skuhne): Do this.
break; break;
case ACTIVITY_PERSISTENT: case ACTIVITY_PERSISTENT:
DCHECK_EQ(ACTIVITY_BACKGROUND_LOW_PRIORITY, current_state); DCHECK_EQ(ACTIVITY_BACKGROUND_LOW_PRIORITY, current_state_);
// TODO(skuhne): Do this. // TODO(skuhne): Do this.
break; break;
case ACTIVITY_UNLOADED: case ACTIVITY_UNLOADED:
DCHECK_NE(ACTIVITY_UNLOADED, current_state); DCHECK_NE(ACTIVITY_UNLOADED, current_state_);
// This will cause the application to shut down, close its windows and // TODO(skuhne): Find out how to evict an app from the extension system.
// delete this object. Instead a |AppActivityProxy| will be created as // web_view_->EvictContent();
// place holder.
if (app_activity_registry_)
app_activity_registry_->Unload();
break; break;
} }
// Remember the last requested state.
current_state_ = state;
} }
Activity::ActivityState AppActivity::GetCurrentState() { Activity::ActivityState AppActivity::GetCurrentState() {
// TODO(skuhne): Check here also eviction status.
if (!web_view_) { if (!web_view_) {
DCHECK_EQ(ACTIVITY_UNLOADED, current_state_); DCHECK_EQ(ACTIVITY_UNLOADED, current_state_);
return ACTIVITY_UNLOADED; return ACTIVITY_UNLOADED;
...@@ -93,10 +82,6 @@ Activity::ActivityMediaState AppActivity::GetMediaState() { ...@@ -93,10 +82,6 @@ Activity::ActivityMediaState AppActivity::GetMediaState() {
return Activity::ACTIVITY_MEDIA_STATE_NONE; return Activity::ACTIVITY_MEDIA_STATE_NONE;
} }
aura::Window* AppActivity::GetWindow() {
return !web_view_ ? NULL : web_view_->GetWidget()->GetNativeWindow();
}
void AppActivity::Init() { void AppActivity::Init() {
} }
...@@ -145,26 +130,4 @@ void AppActivity::DidUpdateFaviconURL( ...@@ -145,26 +130,4 @@ void AppActivity::DidUpdateFaviconURL(
ActivityManager::Get()->UpdateActivity(this); ActivityManager::Get()->UpdateActivity(this);
} }
void AppActivity::DidStartNavigationToPendingEntry(
const GURL& url,
content::NavigationController::ReloadType reload_type) {
if (!app_activity_registry_)
RegisterActivity();
}
// Register an |activity| with an application.
// Note: This should only get called once for an |app_window| of the
// |activity|.
void AppActivity::RegisterActivity() {
content::WebContents* web_contents = app_window_->GetAssociatedWebContents();
AppRegistry* app_registry = AppRegistry::Get();
// Get the application's registry.
app_activity_registry_ = app_registry->GetAppActivityRegistry(
app_registry->GetDelegate()->GetApplicationID(web_contents),
web_contents->GetBrowserContext());
DCHECK(app_activity_registry_);
// Register the activity.
app_activity_registry_->RegisterAppActivity(this);
}
} // namespace athena } // namespace athena
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef ATHENA_CONTENT_APP_ACTIVITY_H_ #ifndef ATHENA_CONTENT_PUBLIC_APP_ACTIVITY_H_
#define ATHENA_CONTENT_APP_ACTIVITY_H_ #define ATHENA_CONTENT_PUBLIC_APP_ACTIVITY_H_
#include "athena/activity/public/activity.h" #include "athena/activity/public/activity.h"
#include "athena/activity/public/activity_view_model.h" #include "athena/activity/public/activity_view_model.h"
...@@ -20,9 +20,6 @@ class WebView; ...@@ -20,9 +20,6 @@ class WebView;
namespace athena { namespace athena {
class AppActivityRegistry;
// The activity object for a hosted V2 application.
class AppActivity : public Activity, class AppActivity : public Activity,
public ActivityViewModel, public ActivityViewModel,
public content::WebContentsObserver { public content::WebContentsObserver {
...@@ -30,13 +27,13 @@ class AppActivity : public Activity, ...@@ -30,13 +27,13 @@ class AppActivity : public Activity,
explicit AppActivity(extensions::ShellAppWindow* app_window); explicit AppActivity(extensions::ShellAppWindow* app_window);
virtual ~AppActivity(); virtual ~AppActivity();
protected:
// Activity: // Activity:
virtual athena::ActivityViewModel* GetActivityViewModel() OVERRIDE; virtual athena::ActivityViewModel* GetActivityViewModel() OVERRIDE;
virtual void SetCurrentState(Activity::ActivityState state) OVERRIDE; virtual void SetCurrentState(Activity::ActivityState state) OVERRIDE;
virtual ActivityState GetCurrentState() OVERRIDE; virtual ActivityState GetCurrentState() OVERRIDE;
virtual bool IsVisible() OVERRIDE; virtual bool IsVisible() OVERRIDE;
virtual ActivityMediaState GetMediaState() OVERRIDE; virtual ActivityMediaState GetMediaState() OVERRIDE;
virtual aura::Window* GetWindow() OVERRIDE;
// ActivityViewModel: // ActivityViewModel:
virtual void Init() OVERRIDE; virtual void Init() OVERRIDE;
...@@ -47,20 +44,13 @@ class AppActivity : public Activity, ...@@ -47,20 +44,13 @@ class AppActivity : public Activity,
virtual void CreateOverviewModeImage() OVERRIDE; virtual void CreateOverviewModeImage() OVERRIDE;
virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE; virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE;
protected:
// content::WebContentsObserver: // content::WebContentsObserver:
virtual void TitleWasSet(content::NavigationEntry* entry, virtual void TitleWasSet(content::NavigationEntry* entry,
bool explicit_set) OVERRIDE; bool explicit_set) OVERRIDE;
virtual void DidUpdateFaviconURL( virtual void DidUpdateFaviconURL(
const std::vector<content::FaviconURL>& candidates) OVERRIDE; const std::vector<content::FaviconURL>& candidates) OVERRIDE;
virtual void DidStartNavigationToPendingEntry(
const GURL& url,
content::NavigationController::ReloadType reload_type) OVERRIDE;
private: private:
// Register this activity with its application.
void RegisterActivity();
scoped_ptr<extensions::ShellAppWindow> app_window_; scoped_ptr<extensions::ShellAppWindow> app_window_;
views::WebView* web_view_; views::WebView* web_view_;
...@@ -70,11 +60,6 @@ class AppActivity : public Activity, ...@@ -70,11 +60,6 @@ class AppActivity : public Activity,
// The image which will be used in overview mode. // The image which will be used in overview mode.
gfx::ImageSkia overview_mode_image_; gfx::ImageSkia overview_mode_image_;
// If known the registry which holds all activities for the associated app.
// This object is owned by |AppRegistry| and will be a valid pointer as long
// as this object lives.
AppActivityRegistry* app_activity_registry_;
DISALLOW_COPY_AND_ASSIGN(AppActivity); DISALLOW_COPY_AND_ASSIGN(AppActivity);
}; };
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "athena/content/app_activity_proxy.h"
#include "athena/content/app_activity_registry.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace athena {
AppActivityProxy::AppActivityProxy(ActivityViewModel* view_model,
AppActivityRegistry* creator) :
app_activity_registry_(creator),
title_(view_model->GetTitle()),
image_(view_model->GetOverviewModeImage()),
color_(view_model->GetRepresentativeColor()),
// TODO(skuhne): We probably need to do something better with the view
// (e.g. showing the image).
view_(new views::View()) {}
AppActivityProxy::~AppActivityProxy() {
app_activity_registry_->ProxyDestroyed(this);
}
ActivityViewModel* AppActivityProxy::GetActivityViewModel() {
return this;
}
void AppActivityProxy::SetCurrentState(ActivityState state) {
// We ignore all calls which try to re-load the application at a lower than
// running invisible state.
if (state != ACTIVITY_VISIBLE && state != ACTIVITY_INVISIBLE)
return;
app_activity_registry_->RestartApplication(this);
// Note: This object is now destroyed.
}
Activity::ActivityState AppActivityProxy::GetCurrentState() {
return ACTIVITY_UNLOADED;
}
bool AppActivityProxy::IsVisible() {
return true;
}
Activity::ActivityMediaState AppActivityProxy::GetMediaState() {
// This proxy has never any media playing.
return ACTIVITY_MEDIA_STATE_NONE;
}
aura::Window* AppActivityProxy::GetWindow() {
return view_->GetWidget()->GetNativeWindow();
}
void AppActivityProxy::Init() {
}
SkColor AppActivityProxy::GetRepresentativeColor() const {
return color_;
}
base::string16 AppActivityProxy::GetTitle() const {
return title_;
}
bool AppActivityProxy::UsesFrame() const {
return true;
}
views::View* AppActivityProxy::GetContentsView() {
return view_;
}
void AppActivityProxy::CreateOverviewModeImage() {
// Nothing we can do here.
}
gfx::ImageSkia AppActivityProxy::GetOverviewModeImage() {
return image_;
}
} // namespace athena
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATHENA_CONTENT_APP_ACTIVITY_PROXY_H_
#define ATHENA_CONTENT_APP_ACTIVITY_PROXY_H_
#include <vector>
#include "athena/activity/public/activity.h"
#include "athena/activity/public/activity_view_model.h"
#include "athena/content/app_activity_proxy.h"
#include "ui/gfx/image/image_skia.h"
namespace athena {
class AppActivityRegistry;
// This activity object is a proxy placeholder for the application while it is
// unloaded. When selected it will launch the applciation again and destroy
// itself indirectly.
class AppActivityProxy : public Activity,
public ActivityViewModel {
public:
AppActivityProxy(ActivityViewModel* view_model, AppActivityRegistry* creator);
virtual ~AppActivityProxy();
// Activity overrides:
virtual ActivityViewModel* GetActivityViewModel() OVERRIDE;
virtual void SetCurrentState(ActivityState state) OVERRIDE;
virtual ActivityState GetCurrentState() OVERRIDE;
virtual bool IsVisible() OVERRIDE;
virtual ActivityMediaState GetMediaState() OVERRIDE;
virtual aura::Window* GetWindow() OVERRIDE;
// ActivityViewModel overrides:
virtual void Init() OVERRIDE;
virtual SkColor GetRepresentativeColor() const OVERRIDE;
virtual base::string16 GetTitle() const OVERRIDE;
virtual bool UsesFrame() const OVERRIDE;
virtual views::View* GetContentsView() OVERRIDE;
virtual void CreateOverviewModeImage() OVERRIDE;
virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE;
private:
// The creator of this object which needs to be informed if the object gets
// destroyed or the application should get restarted.
AppActivityRegistry* app_activity_registry_;
// The presentation values.
const base::string16 title_;
const gfx::ImageSkia image_;
const SkColor color_;
// The associated view.
views::View* view_;
DISALLOW_COPY_AND_ASSIGN(AppActivityProxy);
};
} // namespace athena
#endif // ATHENA_CONTENT_APP_ACTIVITY_PROXY_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "athena/content/app_activity_registry.h"
#include "athena/activity/public/activity_manager.h"
#include "athena/content/app_activity.h"
#include "athena/content/app_activity_proxy.h"
#include "athena/content/public/app_content_control_delegate.h"
#include "athena/content/public/app_registry.h"
#include "ui/aura/window.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace athena {
AppActivityRegistry::AppActivityRegistry(
const std::string& app_id,
content::BrowserContext* browser_context) :
app_id_(app_id),
browser_context_(browser_context),
unloaded_activity_proxy_(NULL) {}
AppActivityRegistry::~AppActivityRegistry() {
CHECK(activity_list_.empty());
if (unloaded_activity_proxy_)
ActivityManager::Get()->RemoveActivity(unloaded_activity_proxy_);
DCHECK(!unloaded_activity_proxy_);
}
void AppActivityRegistry::RegisterAppActivity(AppActivity* app_activity) {
if (unloaded_activity_proxy_) {
// Since we add an application window, the activity isn't unloaded anymore.
ActivityManager::Get()->RemoveActivity(unloaded_activity_proxy_);
// With the removal the object should have been deleted and we should have
// been informed of the object's destruction.
DCHECK(!unloaded_activity_proxy_);
}
// The same window should never be added twice.
CHECK(std::find(activity_list_.begin(),
activity_list_.end(),
app_activity) == activity_list_.end());
activity_list_.push_back(app_activity);
}
void AppActivityRegistry::UnregisterAppActivity(AppActivity* app_activity) {
// It is possible that a detach gets called without ever being attached.
std::vector<AppActivity*>::iterator it =
std::find(activity_list_.begin(), activity_list_.end(), app_activity);
if (it == activity_list_.end())
return;
activity_list_.erase(it);
// When the last window gets destroyed and there is no proxy to restart, we
// delete ourselves.
if (activity_list_.empty() && !unloaded_activity_proxy_) {
AppRegistry::Get()->RemoveAppActivityRegistry(this);
// after this call this object should be gone.
}
}
AppActivity* AppActivityRegistry::GetAppActivityAt(size_t index) {
if (index >= activity_list_.size())
return NULL;
return activity_list_[index];
}
void AppActivityRegistry::Unload() {
CHECK(!unloaded_activity_proxy_);
DCHECK(!activity_list_.empty());
// In order to allow an entire application to unload we require that all of
// its activities are marked as unloaded.
for (std::vector<AppActivity*>::iterator it = activity_list_.begin();
it != activity_list_.end(); ++it) {
if ((*it)->GetCurrentState() != Activity::ACTIVITY_UNLOADED)
return;
}
// Create an activity proxy which can be used to re-activate the app. Insert
// the proxy then into the activity stream at the location of the (newest)
// current activity.
unloaded_activity_proxy_ =
new AppActivityProxy(activity_list_[0]->GetActivityViewModel(), this);
ActivityManager::Get()->AddActivity(unloaded_activity_proxy_);
// The new activity should be in the place of the most recently used app
// window. To get it there, we get the most recently used application window
// and place the proxy activities window in front or behind, so that when the
// activity disappears it takes its place.
MoveBeforeMruApplicationWindow(unloaded_activity_proxy_->GetWindow());
// Unload the application. This operation will be asynchronous.
if (!AppRegistry::Get()->GetDelegate()->UnloadApplication(app_id_,
browser_context_)) {
while(!activity_list_.empty())
delete activity_list_.back();
}
}
void AppActivityRegistry::ProxyDestroyed(AppActivityProxy* proxy) {
DCHECK_EQ(unloaded_activity_proxy_, proxy);
unloaded_activity_proxy_ = NULL;
if (activity_list_.empty()) {
AppRegistry::Get()->RemoveAppActivityRegistry(this);
// |This| is gone now.
}
}
void AppActivityRegistry::RestartApplication(AppActivityProxy* proxy) {
DCHECK_EQ(unloaded_activity_proxy_, proxy);
// Restart the application.
AppRegistry::Get()->GetDelegate()->RestartApplication(app_id_,
browser_context_);
// Remove the activity from the Activity manager.
ActivityManager::Get()->RemoveActivity(unloaded_activity_proxy_);
delete unloaded_activity_proxy_; // Will call ProxyDestroyed.
// After this call |this| might be gone if the app did not open a window yet.
}
void AppActivityRegistry::MoveBeforeMruApplicationWindow(aura::Window* window) {
DCHECK(activity_list_.size());
// TODO(skuhne): This needs to be changed to some kind of delegate which
// resides in the window manager.
const aura::Window::Windows children =
activity_list_[0]->GetWindow()->parent()->children();;
// Find the first window in the container which is part of the application.
for (aura::Window::Windows::const_iterator child_iterator = children.begin();
child_iterator != children.end(); ++child_iterator) {
for (std::vector<AppActivity*>::iterator app_iterator =
activity_list_.begin();
app_iterator != activity_list_.end(); ++app_iterator) {
if (*child_iterator == (*app_iterator)->GetWindow()) {
// Since "StackChildBelow" does not change the order if the window
// if the window is below - but not immediately behind - the target
// window, we re-stack both ways.
window->parent()->StackChildBelow(window, *child_iterator);
window->parent()->StackChildBelow(*child_iterator, window);
return;
}
}
}
NOTREACHED() << "The application does not get tracked by the mru list";
}
} // namespace athena
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATHENA_CONTENT_APP_ACTIVITY_REGISTRY_H_
#define ATHENA_CONTENT_APP_ACTIVITY_REGISTRY_H_
#include <vector>
#include "athena/activity/public/activity_view_model.h"
#include "athena/content/app_activity_proxy.h"
namespace aura {
class Window;
}
namespace content {
class BrowserContext;
}
namespace athena {
class AppActivity;
// This class keeps track of all existing |AppActivity|s and shuts down all of
// them when the application gets unloaded to save memory. It will then replace
// the |AppActivity| in the Activity list as proxy to allow restarting of the
// application.
class ATHENA_EXPORT AppActivityRegistry {
public:
AppActivityRegistry(const std::string& app_id,
content::BrowserContext* browser_context);
virtual ~AppActivityRegistry();
// Register an |AppActivity| with this application.
void RegisterAppActivity(AppActivity* app_activity);
// Unregister a previously attached |AppActivity|.
// Note that detaching the last |AppActivity| will delete this object - unless
// the resource manager was trying to unload the application.
// Note furthermore that Detach can be called without ever being registered.
void UnregisterAppActivity(AppActivity* app_activity);
// Returns the number of activities/windows with this application.
int NumberOfActivities() const { return activity_list_.size(); }
// Returns the |AppActivity| at |index|. It will return NULL if an invalid
// index was specified.
AppActivity* GetAppActivityAt(size_t index);
// Unload all application associated activities to save resources.
void Unload();
// Returns true if the application is in the unloaded state.
bool IsUnloaded() { return unloaded_activity_proxy_ != NULL; }
content::BrowserContext* browser_context() const { return browser_context_; }
const std::string& app_id() const { return app_id_; }
AppActivityProxy* unloaded_activity_proxy_for_test() {
return unloaded_activity_proxy_;
}
protected:
friend AppActivityProxy;
// When the |AppActivityProxy| gets destroyed it should call this function
// to disconnect from this object. This call might destroy |this|.
void ProxyDestroyed(AppActivityProxy* proxy);
// When called by the |AppActivityProxy| to restart the application, it can
// cause the application to restart. When that happens the proxy will get
// destroyed. After this call |this| might be destroyed.
void RestartApplication(AppActivityProxy* proxy);
private:
// Move the window before the most recently used application window.
void MoveBeforeMruApplicationWindow(aura::Window* window);
// A list of all activities associated with this application.
std::vector<AppActivity*> activity_list_;
// The application id for this proxy.
std::string app_id_;
// The browser context of the user.
content::BrowserContext* browser_context_;
// When the activity is unloaded this is the AppActivityProxy. The object is
// owned the the ActivityManager.
AppActivityProxy* unloaded_activity_proxy_;
// The presentation values.
SkColor color_;
base::string16 title_;
gfx::ImageSkia image_;
DISALLOW_COPY_AND_ASSIGN(AppActivityRegistry);
};
} // namespace athena
#endif // ATHENA_CONTENT_APP_ACTIVITY_REGISTRY_H_
This diff is collapsed.
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "athena/content/public/app_registry.h"
#include "athena/content/app_activity_registry.h"
#include "athena/content/public/app_content_control_delegate.h"
#include "base/logging.h"
namespace athena {
class AppRegistryImpl : public AppRegistry {
public:
AppRegistryImpl();
virtual ~AppRegistryImpl();
// AppRegistry:
virtual void SetDelegate(AppContentControlDelegate* delegate) OVERRIDE;
virtual AppContentControlDelegate* GetDelegate() OVERRIDE;
virtual AppActivityRegistry* GetAppActivityRegistry(
const std::string& app_id,
content::BrowserContext* browser_context) OVERRIDE;
virtual int NumberOfApplications() const OVERRIDE { return app_list_.size(); }
private:
virtual void RemoveAppActivityRegistry(
AppActivityRegistry* registry) OVERRIDE;
std::vector<AppActivityRegistry*> app_list_;
scoped_ptr<AppContentControlDelegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(AppRegistryImpl);
};
namespace {
AppRegistryImpl* instance = NULL;
} // namespace
AppRegistryImpl::AppRegistryImpl() :
delegate_(AppContentControlDelegate::CreateAppContentControlDelegate()) {}
AppRegistryImpl::~AppRegistryImpl() {
DCHECK(app_list_.empty());
}
void AppRegistryImpl::SetDelegate(AppContentControlDelegate* delegate) {
DCHECK(delegate);
delegate_.reset(delegate);
}
AppContentControlDelegate* AppRegistryImpl::GetDelegate() {
return delegate_.get();
}
AppActivityRegistry* AppRegistryImpl::GetAppActivityRegistry(
const std::string& app_id,
content::BrowserContext* browser_context) {
// Search for an existing proxy.
for (std::vector<AppActivityRegistry*>::iterator it = app_list_.begin();
it != app_list_.end(); ++it) {
if ((*it)->app_id() == app_id &&
(*it)->browser_context() == browser_context)
return *it;
}
// Create and return a new application object.
AppActivityRegistry* app_activity_registry =
new AppActivityRegistry(app_id, browser_context);
app_list_.push_back(app_activity_registry);
return app_activity_registry;
}
void AppRegistryImpl::RemoveAppActivityRegistry(AppActivityRegistry* registry) {
std::vector<AppActivityRegistry*>::iterator item =
std::find(app_list_.begin(), app_list_.end(), registry);
CHECK(item != app_list_.end());
app_list_.erase(item);
}
// static
void AppRegistry::Create() {
DCHECK(!instance);
instance = new AppRegistryImpl();
}
// static
AppRegistry* AppRegistry::Get() {
DCHECK(instance);
return instance;
}
// static
void AppRegistry::ShutDown() {
DCHECK(instance);
delete instance;
}
AppRegistry::AppRegistry() {}
AppRegistry::~AppRegistry() {
instance = NULL;
}
} // namespace athena
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "athena/content/public/app_content_control_delegate.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/api/app_runtime/app_runtime_api.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h"
namespace athena {
class AppContentControlDelegateImpl : public AppContentControlDelegate {
public:
AppContentControlDelegateImpl() {}
virtual ~AppContentControlDelegateImpl() {}
// AppContentControlDelegate:
virtual bool UnloadApplication(
const std::string& app_id,
content::BrowserContext* browser_context) OVERRIDE;
virtual bool RestartApplication(
const std::string& app_id,
content::BrowserContext* browser_context) OVERRIDE;
virtual std::string GetApplicationID(
content::WebContents* web_contents) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(AppContentControlDelegateImpl);
};
bool AppContentControlDelegateImpl::UnloadApplication(
const std::string& app_id,
content::BrowserContext* browser_context) {
// TODO(skuhne): Use the extension system to unload
// (|ExtensionService::TerminateExtension|) once it becomes available in
// Athena.
return false;
}
bool AppContentControlDelegateImpl::RestartApplication(
const std::string& app_id,
content::BrowserContext* browser_context) {
// TODO(skuhne): As soon as the ExtensionSystem can be used, we should use the
// proper commands here for restarting.
const extensions::Extension* extension =
extensions::ExtensionRegistry::Get(browser_context)->GetExtensionById(
app_id, extensions::ExtensionRegistry::EVERYTHING);
DCHECK(extension);
extensions::AppRuntimeEventRouter::DispatchOnLaunchedEvent(browser_context,
extension);
return true;
}
// Get the extension Id from a given |web_contents|.
std::string AppContentControlDelegateImpl::GetApplicationID(
content::WebContents* web_contents) {
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
// This works for both apps and extensions because the site has been
// normalized to the extension URL for hosted apps.
content::SiteInstance* site_instance = render_view_host->GetSiteInstance();
if (!site_instance)
return std::string();
const GURL& site_url = site_instance->GetSiteURL();
if (!site_url.SchemeIs(extensions::kExtensionScheme))
return std::string();
return site_url.host();
}
// static
AppContentControlDelegate*
AppContentControlDelegate::CreateAppContentControlDelegate() {
return new AppContentControlDelegateImpl;
}
} // namespace athena
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATHENA_CONTENT_PUBLIC_APP_CONTENT_CONTROL_DLEGATE_H_
#define ATHENA_CONTENT_PUBLIC_APP_CONTENT_CONTROL_DLEGATE_H_
#include <string>
#include "base/macros.h"
namespace content {
class BrowserContext;
class WebContents;
}
namespace athena {
// The application content delegate which can be overwritten for unit tests to
// eliminate dependencies to the content / browser system.
class AppContentControlDelegate {
public:
static AppContentControlDelegate* CreateAppContentControlDelegate();
AppContentControlDelegate() {}
virtual ~AppContentControlDelegate() {}
// Unload an application. Returns true when unloaded.
virtual bool UnloadApplication(const std::string& app_id,
content::BrowserContext* browser_context) = 0;
// Restarts an application. Returns true when the restart was initiated.
virtual bool RestartApplication(const std::string& app_id,
content::BrowserContext* browser_context) = 0;
// Returns the application ID (or an empty string) for a given web content.
virtual std::string GetApplicationID(content::WebContents* web_contents) = 0;
};
} // namespace athena
#endif // ATHENA_CONTENT_PUBLIC_APP_CONTENT_CONTROL_DLEGATE_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATHENA_CONTENT_PUBLIC_APP_REGISTRY_H_
#define ATHENA_CONTENT_PUBLIC_APP_REGISTRY_H_
#include <string>
#include <vector>
#include "athena/athena_export.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
namespace content {
class BrowserContext;
}
namespace athena {
class AppActivityRegistry;
class AppContentControlDelegate;
class AppRegistryImpl;
// This class holds for each application, held by a user, a list of activities.
// The list of activities can be retrieved as |AppActivityRegistry|. It is used
// to associate activities with applications and allow the resource manager to
// (re)start and stop applications.
class ATHENA_EXPORT AppRegistry {
public:
// Creates the AppRegistry instance.
static void Create();
// Gets the instance of the controller.
static AppRegistry* Get();
// Shuts down the registry (all applications should be shut down by then).
static void ShutDown();
// Overrides the used AppContentDelegate. This function will own it
// afterwards. A value of NULL is invalid.
virtual void SetDelegate(AppContentControlDelegate* delegate) = 0;
// Retrieves the application content delegate. The ownership remains with this
// class.
virtual AppContentControlDelegate* GetDelegate() = 0;
// Returns an |AppActivityRegistry| for a given activity |app_id| and
// |browser_context|.
virtual AppActivityRegistry* GetAppActivityRegistry(
const std::string& app_id,
content::BrowserContext* browser_context) = 0;
// Returns the number of registered applications.
virtual int NumberOfApplications() const = 0;
protected:
// Only the |AppActivityRegistry| can remove itself.
friend AppActivityRegistry;
// Removes an activity registry for an application from the list of known
// applications.
virtual void RemoveAppActivityRegistry(AppActivityRegistry* registry) = 0;
// Constructor and destructor can only be called by the implementing class.
AppRegistry();
virtual ~AppRegistry();
};
} // namespace athena
#endif // ATHENA_CONTENT_PUBLIC_APP_REGISTRY_H_
...@@ -347,10 +347,6 @@ Activity::ActivityMediaState WebActivity::GetMediaState() { ...@@ -347,10 +347,6 @@ Activity::ActivityMediaState WebActivity::GetMediaState() {
return Activity::ACTIVITY_MEDIA_STATE_NONE; return Activity::ACTIVITY_MEDIA_STATE_NONE;
} }
aura::Window* WebActivity::GetWindow() {
return !web_view_ ? NULL : web_view_->GetWidget()->GetNativeWindow();
}
void WebActivity::Init() { void WebActivity::Init() {
DCHECK(web_view_); DCHECK(web_view_);
web_view_->InstallAccelerators(); web_view_->InstallAccelerators();
......
...@@ -39,7 +39,6 @@ class WebActivity : public Activity, ...@@ -39,7 +39,6 @@ class WebActivity : public Activity,
virtual ActivityState GetCurrentState() OVERRIDE; virtual ActivityState GetCurrentState() OVERRIDE;
virtual bool IsVisible() OVERRIDE; virtual bool IsVisible() OVERRIDE;
virtual ActivityMediaState GetMediaState() OVERRIDE; virtual ActivityMediaState GetMediaState() OVERRIDE;
virtual aura::Window* GetWindow() OVERRIDE;
// ActivityViewModel: // ActivityViewModel:
virtual void Init() OVERRIDE; virtual void Init() OVERRIDE;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "athena/activity/public/activity_factory.h" #include "athena/activity/public/activity_factory.h"
#include "athena/activity/public/activity_manager.h" #include "athena/activity/public/activity_manager.h"
#include "athena/content/public/app_registry.h"
#include "athena/content/public/content_activity_factory.h" #include "athena/content/public/content_activity_factory.h"
#include "athena/content/public/content_app_model_builder.h" #include "athena/content/public/content_app_model_builder.h"
#include "athena/home/public/home_card.h" #include "athena/home/public/home_card.h"
...@@ -120,7 +119,6 @@ void StartAthenaEnv(aura::Window* root_window, ...@@ -120,7 +119,6 @@ void StartAthenaEnv(aura::Window* root_window,
athena::InputManager::Create()->OnRootWindowCreated(root_window); athena::InputManager::Create()->OnRootWindowCreated(root_window);
athena::ScreenManager::Create(delegate, root_window); athena::ScreenManager::Create(delegate, root_window);
athena::WindowManager::Create(); athena::WindowManager::Create();
athena::AppRegistry::Create();
SetupBackgroundImage(); SetupBackgroundImage();
athena::ScreenManager::Get()->GetContext()->SetProperty( athena::ScreenManager::Get()->GetContext()->SetProperty(
...@@ -153,7 +151,6 @@ void ShutdownAthena() { ...@@ -153,7 +151,6 @@ void ShutdownAthena() {
athena::ActivityFactory::Shutdown(); athena::ActivityFactory::Shutdown();
athena::ActivityManager::Shutdown(); athena::ActivityManager::Shutdown();
athena::HomeCard::Shutdown(); athena::HomeCard::Shutdown();
athena::AppRegistry::ShutDown();
athena::WindowManager::Shutdown(); athena::WindowManager::Shutdown();
athena::ScreenManager::Shutdown(); athena::ScreenManager::Shutdown();
athena::InputManager::Shutdown(); athena::InputManager::Shutdown();
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
'dependencies': [ 'dependencies': [
'../athena.gyp:athena_lib', '../athena.gyp:athena_lib',
'../athena.gyp:athena_content_lib', '../athena.gyp:athena_content_lib',
'../athena.gyp:athena_content_support_lib',
'../resources/athena_resources.gyp:athena_resources', '../resources/athena_resources.gyp:athena_resources',
# debug_widow.cc depends on this. Remove this once debug_window # debug_widow.cc depends on this. Remove this once debug_window
# is removed. # is removed.
......
include_rules = [ include_rules = [
"+athena/activity", "+athena/activity",
"+athena/content/public",
"+athena/home/public", "+athena/home/public",
"+athena/main", "+athena/main",
"+athena/screen/public", "+athena/screen/public",
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/view.h" #include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace athena { namespace athena {
namespace test { namespace test {
...@@ -44,11 +43,6 @@ Activity::ActivityMediaState SampleActivity::GetMediaState() { ...@@ -44,11 +43,6 @@ Activity::ActivityMediaState SampleActivity::GetMediaState() {
return Activity::ACTIVITY_MEDIA_STATE_NONE; return Activity::ACTIVITY_MEDIA_STATE_NONE;
} }
aura::Window* SampleActivity::GetWindow() {
return
!contents_view_ ? NULL : contents_view_->GetWidget()->GetNativeWindow();
}
void SampleActivity::Init() { void SampleActivity::Init() {
} }
......
...@@ -28,7 +28,6 @@ class SampleActivity : public Activity, ...@@ -28,7 +28,6 @@ class SampleActivity : public Activity,
virtual ActivityState GetCurrentState() OVERRIDE; virtual ActivityState GetCurrentState() OVERRIDE;
virtual bool IsVisible() OVERRIDE; virtual bool IsVisible() OVERRIDE;
virtual ActivityMediaState GetMediaState() OVERRIDE; virtual ActivityMediaState GetMediaState() OVERRIDE;
virtual aura::Window* GetWindow() OVERRIDE;
// athena::ActivityViewModel: // athena::ActivityViewModel:
virtual void Init() OVERRIDE; virtual void Init() OVERRIDE;
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "athena/content/public/app_content_control_delegate.h"
namespace athena {
class AppContentControlDelegateImpl : public AppContentControlDelegate {
public:
AppContentControlDelegateImpl() {}
virtual ~AppContentControlDelegateImpl() {}
virtual bool UnloadApplication(
const std::string& app_id,
content::BrowserContext* browser_context) OVERRIDE;
virtual bool RestartApplication(
const std::string& app_id,
content::BrowserContext* browser_context) OVERRIDE;
virtual std::string GetApplicationID(
content::WebContents* web_contents) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(AppContentControlDelegateImpl);
};
bool AppContentControlDelegateImpl::UnloadApplication(
const std::string& app_id,
content::BrowserContext* browser_context) {
// TODO(skuhne): Use the extension system to unload
// (|ExtensionService::TerminateExtension|) once it becomes available in
// Athena.
return false;
}
bool AppContentControlDelegateImpl::RestartApplication(
const std::string& app_id,
content::BrowserContext* browser_context) {
return false;
}
std::string AppContentControlDelegateImpl::GetApplicationID(
content::WebContents* web_contents) {
return std::string();
}
// static
AppContentControlDelegate*
AppContentControlDelegate::CreateAppContentControlDelegate() {
return new AppContentControlDelegateImpl;
}
} // namespace athena
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment