Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / athena / content / app_activity.cc
index c90daff..8768508 100644 (file)
@@ -5,23 +5,36 @@
 #include "athena/content/app_activity.h"
 
 #include "athena/activity/public/activity_manager.h"
+#include "athena/content/app_activity_registry.h"
+#include "athena/content/content_proxy.h"
+#include "athena/content/public/app_registry.h"
+#include "athena/wm/public/window_list_provider.h"
+#include "athena/wm/public/window_manager.h"
 #include "content/public/browser/web_contents.h"
-#include "extensions/shell/browser/shell_app_window.h"
+#include "extensions/browser/app_window/app_window.h"
+#include "ui/aura/window.h"
 #include "ui/views/controls/webview/webview.h"
+#include "ui/views/widget/widget.h"
 
 namespace athena {
 
 // TODO(mukai): specifies the same accelerators of WebActivity.
-AppActivity::AppActivity(extensions::ShellAppWindow* app_window)
-    : app_window_(app_window),
-      web_view_(NULL),
-      current_state_(ACTIVITY_UNLOADED) {
-  DCHECK(app_window_);
+AppActivity::AppActivity(extensions::AppWindow* app_window,
+                         views::WebView* web_view)
+    : app_id_(app_window->extension_id()),
+      web_view_(web_view),
+      current_state_(ACTIVITY_UNLOADED),
+      app_activity_registry_(NULL) {
+  DCHECK_EQ(app_window->web_contents(), web_view->GetWebContents());
+  Observe(app_window->web_contents());
 }
 
-AppActivity::~AppActivity() {
-  if (GetCurrentState() != ACTIVITY_UNLOADED)
-    SetCurrentState(ACTIVITY_UNLOADED);
+scoped_ptr<ContentProxy> AppActivity::GetContentProxy() {
+  // Note: After this call, the content is still valid because the contents
+  // destruction will destroy this |AppActivity| object.
+  if (content_proxy_.get())
+    content_proxy_->OnPreContentDestroyed();
+  return content_proxy_.Pass();
 }
 
 ActivityViewModel* AppActivity::GetActivityViewModel() {
@@ -29,50 +42,49 @@ ActivityViewModel* AppActivity::GetActivityViewModel() {
 }
 
 void AppActivity::SetCurrentState(Activity::ActivityState state) {
+  DCHECK_NE(state, current_state_);
+  ActivityState current_state = current_state_;
+  // Remember the last requested state now so that a call to GetCurrentState()
+  // returns the new state.
+  current_state_ = state;
+
   switch (state) {
     case ACTIVITY_VISIBLE:
-      // Fall through (for the moment).
+      HideContentProxy();
+      return;
     case ACTIVITY_INVISIBLE:
-      // By clearing the overview mode image we allow the content to be shown.
-      overview_mode_image_ = gfx::ImageSkia();
-      // TODO(skuhne): Find out how to reload an app from the extension system.
+      if (current_state == ACTIVITY_VISIBLE)
+        ShowContentProxy();
       break;
     case ACTIVITY_BACKGROUND_LOW_PRIORITY:
-      DCHECK(ACTIVITY_VISIBLE == current_state_ ||
-             ACTIVITY_INVISIBLE == current_state_);
+      DCHECK(ACTIVITY_VISIBLE == current_state ||
+             ACTIVITY_INVISIBLE == current_state);
       // TODO(skuhne): Do this.
       break;
     case ACTIVITY_PERSISTENT:
-      DCHECK_EQ(ACTIVITY_BACKGROUND_LOW_PRIORITY, current_state_);
+      DCHECK_EQ(ACTIVITY_BACKGROUND_LOW_PRIORITY, current_state);
       // TODO(skuhne): Do this.
       break;
     case ACTIVITY_UNLOADED:
-      DCHECK_NE(ACTIVITY_UNLOADED, current_state_);
-      // TODO(skuhne): Find out how to evict an app from the extension system.
-      //      web_view_->EvictContent();
+      DCHECK_NE(ACTIVITY_UNLOADED, current_state);
+      // This will cause the application to shut down, close its windows and
+      // delete this object. Instead a |AppActivityProxy| will be created as
+      // place holder.
+      if (app_activity_registry_)
+        app_activity_registry_->Unload();
       break;
   }
-  // Remember the last requested state.
-  current_state_ = state;
 }
 
 Activity::ActivityState AppActivity::GetCurrentState() {
-  // TODO(skuhne): Check here also eviction status.
-  if (!web_view_) {
-    DCHECK_EQ(ACTIVITY_UNLOADED, current_state_);
-    return ACTIVITY_UNLOADED;
-  }
-  // TODO(skuhne): This should be controlled by an observer and should not
-  // reside here.
-  if (IsVisible() && current_state_ != ACTIVITY_VISIBLE)
-    SetCurrentState(ACTIVITY_VISIBLE);
-  // Note: If the activity is not visible it does not necessarily mean that it
-  // does not have GPU compositor resources (yet).
+  DCHECK(web_view_ || ACTIVITY_UNLOADED == current_state_);
   return current_state_;
 }
 
 bool AppActivity::IsVisible() {
-  return web_view_ && web_view_->IsDrawn();
+  return web_view_ &&
+         web_view_->visible() &&
+         current_state_ != ACTIVITY_UNLOADED;
 }
 
 Activity::ActivityMediaState AppActivity::GetMediaState() {
@@ -82,7 +94,28 @@ Activity::ActivityMediaState AppActivity::GetMediaState() {
   return Activity::ACTIVITY_MEDIA_STATE_NONE;
 }
 
+aura::Window* AppActivity::GetWindow() {
+  return !web_view_ ? NULL : web_view_->GetWidget()->GetNativeWindow();
+}
+
+content::WebContents* AppActivity::GetWebContents() {
+  return !web_view_ ? NULL : web_view_->GetWebContents();
+}
+
 void AppActivity::Init() {
+  DCHECK(app_activity_registry_);
+  Activity* app_proxy = app_activity_registry_->unloaded_activity_proxy();
+  if (app_proxy) {
+    // Note: At this time the |AppActivity| did not get registered to the
+    // |ResourceManager| - so we can move it around if needed.
+    WindowListProvider* window_list_provider =
+        WindowManager::Get()->GetWindowListProvider();
+    window_list_provider->StackWindowFrontOf(app_proxy->GetWindow(),
+                                             GetWindow());
+    Activity::Delete(app_proxy);
+    // With the removal the object, the proxy should be deleted.
+    DCHECK(!app_activity_registry_->unloaded_activity_proxy());
+  }
 }
 
 SkColor AppActivity::GetRepresentativeColor() const {
@@ -94,30 +127,65 @@ base::string16 AppActivity::GetTitle() const {
   return web_view_->GetWebContents()->GetTitle();
 }
 
+gfx::ImageSkia AppActivity::GetIcon() const {
+  return gfx::ImageSkia();
+}
+
 bool AppActivity::UsesFrame() const {
   return false;
 }
 
-views::View* AppActivity::GetContentsView() {
-  if (!web_view_) {
-    // TODO(oshima): use apps::NativeAppWindowViews
-    content::WebContents* web_contents =
-        app_window_->GetAssociatedWebContents();
-    web_view_ = new views::WebView(web_contents->GetBrowserContext());
-    web_view_->SetWebContents(web_contents);
+views::Widget* AppActivity::CreateWidget() {
+  // Make sure the content gets properly shown.
+  if (current_state_ == ACTIVITY_VISIBLE) {
+    HideContentProxy();
+  } else if (current_state_ == ACTIVITY_INVISIBLE) {
+    ShowContentProxy();
+  } else {
+    // If not previously specified, we change the state now to invisible..
     SetCurrentState(ACTIVITY_INVISIBLE);
-    Observe(web_contents);
-    overview_mode_image_ = gfx::ImageSkia();
   }
-  return web_view_;
+  RegisterActivity();
+  return web_view_->GetWidget();
 }
 
-void AppActivity::CreateOverviewModeImage() {
-  // TODO(skuhne): Implement this!
+views::View* AppActivity::GetContentsView() {
+  return web_view_;
 }
 
 gfx::ImageSkia AppActivity::GetOverviewModeImage() {
-  return overview_mode_image_;
+  if (content_proxy_.get())
+    return content_proxy_->GetContentImage();
+  return gfx::ImageSkia();
+}
+
+void AppActivity::PrepareContentsForOverview() {
+  // Turn on fast resizing to avoid re-laying out the web contents when
+  // entering / exiting overview mode and the content is visible.
+  if (!content_proxy_.get())
+    web_view_->SetFastResize(true);
+}
+
+void AppActivity::ResetContentsView() {
+  // Turn on fast resizing to avoid re-laying out the web contents when
+  // entering / exiting overview mode and the content is visible.
+  if (!content_proxy_.get()) {
+    web_view_->SetFastResize(false);
+    web_view_->Layout();
+  }
+}
+
+AppActivity::AppActivity(const std::string& app_id)
+    : app_id_(app_id),
+      web_view_(NULL),
+      current_state_(ACTIVITY_UNLOADED),
+      app_activity_registry_(NULL) {
+}
+
+AppActivity::~AppActivity() {
+  // If this activity is registered, we unregister it now.
+  if (app_activity_registry_)
+    app_activity_registry_->UnregisterAppActivity(this);
 }
 
 void AppActivity::TitleWasSet(content::NavigationEntry* entry,
@@ -130,4 +198,27 @@ void AppActivity::DidUpdateFaviconURL(
   ActivityManager::Get()->UpdateActivity(this);
 }
 
+// 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 = web_view_->GetWebContents();
+  AppRegistry* app_registry = AppRegistry::Get();
+  // Get the application's registry.
+  app_activity_registry_ = app_registry->GetAppActivityRegistry(
+      app_id_, web_contents->GetBrowserContext());
+  DCHECK(app_activity_registry_);
+  // Register the activity.
+  app_activity_registry_->RegisterAppActivity(this);
+}
+
+void AppActivity::HideContentProxy() {
+  content_proxy_.reset();
+}
+
+void AppActivity::ShowContentProxy() {
+  if (!content_proxy_.get() && web_view_)
+    content_proxy_.reset(new ContentProxy(web_view_, this));
+}
+
 }  // namespace athena