普通文本  |  225行  |  7.08 KB

// 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.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/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::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());
}

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() {
  return this;
}

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:
      HideContentProxy();
      return;
    case ACTIVITY_INVISIBLE:
      if (current_state == ACTIVITY_VISIBLE)
        ShowContentProxy();
      break;
    case ACTIVITY_BACKGROUND_LOW_PRIORITY:
      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);
      // TODO(skuhne): Do this.
      break;
    case ACTIVITY_UNLOADED:
      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;
  }
}

Activity::ActivityState AppActivity::GetCurrentState() {
  DCHECK(web_view_ || ACTIVITY_UNLOADED == current_state_);
  return current_state_;
}

bool AppActivity::IsVisible() {
  return web_view_ &&
         web_view_->visible() &&
         current_state_ != ACTIVITY_UNLOADED;
}

Activity::ActivityMediaState AppActivity::GetMediaState() {
  // TODO(skuhne): The function GetTabMediaStateForContents(WebContents),
  // and the AudioStreamMonitor needs to be moved from Chrome into contents to
  // make it more modular and so that we can use it from here.
  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 {
  // TODO(sad): Compute the color from the favicon.
  return SK_ColorGRAY;
}

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::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);
  }
  RegisterActivity();
  return web_view_->GetWidget();
}

views::View* AppActivity::GetContentsView() {
  return web_view_;
}

gfx::ImageSkia AppActivity::GetOverviewModeImage() {
  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,
                              bool explicit_set) {
  ActivityManager::Get()->UpdateActivity(this);
}

void AppActivity::DidUpdateFaviconURL(
    const std::vector<content::FaviconURL>& candidates) {
  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