| Index: athena/content/web_activity.cc
|
| diff --git a/athena/content/web_activity.cc b/athena/content/web_activity.cc
|
| index 70439c670475158dea8c4137eb8c6ebbe1b92a6a..69d44f09369eeacbdc654cf172c33bb5d41a8519 100644
|
| --- a/athena/content/web_activity.cc
|
| +++ b/athena/content/web_activity.cc
|
| @@ -116,15 +116,57 @@ class WebActivityController : public AcceleratorHandler {
|
| DISALLOW_COPY_AND_ASSIGN(WebActivityController);
|
| };
|
|
|
| -// A web view for athena's web activity.
|
| +} // namespace
|
| +
|
| +// A web view for athena's web activity. Note that AthenaWebView will create its
|
| +// own content so that it can eject and reload it.
|
| class AthenaWebView : public views::WebView {
|
| public:
|
| AthenaWebView(content::BrowserContext* context)
|
| - : views::WebView(context), controller_(new WebActivityController(this)) {}
|
| - virtual ~AthenaWebView() {}
|
| + : views::WebView(context), controller_(new WebActivityController(this)) {
|
| + // We create the first web contents ourselves to allow us to replace it
|
| + // later on.
|
| + SetWebContents(content::WebContents::Create(
|
| + content::WebContents::CreateParams(context)));
|
| + // TODO(skuhne): Add content observer to detect renderer crash and set
|
| + // content status to unloaded if that happens.
|
| + }
|
| + virtual ~AthenaWebView() {
|
| + // |WebView| does not own the content, so we need to destroy it here.
|
| + content::WebContents* current_contents = GetWebContents();
|
| + SetWebContents(NULL);
|
| + delete current_contents;
|
| + }
|
|
|
| void InstallAccelerators() { controller_->InstallAccelerators(); }
|
|
|
| + void EvictContent() {
|
| + content::WebContents* old_contents = GetWebContents();
|
| + evicted_web_contents_.reset(
|
| + content::WebContents::Create(content::WebContents::CreateParams(
|
| + old_contents->GetBrowserContext())));
|
| + evicted_web_contents_->GetController().CopyStateFrom(
|
| + old_contents->GetController());
|
| + SetWebContents(content::WebContents::Create(
|
| + content::WebContents::CreateParams(old_contents->GetBrowserContext())));
|
| + delete old_contents;
|
| + // As soon as the new contents becomes visible, it should reload.
|
| + // TODO(skuhne): This breaks script connections with other activities.
|
| + // Even though this is the same technique as used by the TabStripModel,
|
| + // we might want to address this cleaner since we are more likely to
|
| + // run into this state. by unloading.
|
| + }
|
| +
|
| + void ReloadContent() {
|
| + CHECK(evicted_web_contents_.get());
|
| + content::WebContents* null_contents = GetWebContents();
|
| + SetWebContents(evicted_web_contents_.release());
|
| + delete null_contents;
|
| + }
|
| +
|
| + // Check if the content got evicted.
|
| + const bool IsContentEvicted() { return !!evicted_web_contents_.get(); }
|
| +
|
| private:
|
| // WebContentsDelegate:
|
| virtual bool PreHandleKeyboardEvent(
|
| @@ -143,28 +185,92 @@ class AthenaWebView : public views::WebView {
|
|
|
| scoped_ptr<WebActivityController> controller_;
|
|
|
| + // If the activity got evicted, this is the web content which holds the known
|
| + // state of the content before eviction.
|
| + scoped_ptr<content::WebContents> evicted_web_contents_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(AthenaWebView);
|
| };
|
|
|
| -} // namespace
|
| -
|
| WebActivity::WebActivity(content::BrowserContext* browser_context,
|
| const GURL& url)
|
| : browser_context_(browser_context),
|
| url_(url),
|
| - web_view_(NULL) {
|
| + web_view_(NULL),
|
| + current_state_(ACTIVITY_UNLOADED) {
|
| }
|
|
|
| WebActivity::~WebActivity() {
|
| + // It is not required to change the activity state to UNLOADED - unless we
|
| + // would add state observers.
|
| }
|
|
|
| ActivityViewModel* WebActivity::GetActivityViewModel() {
|
| return this;
|
| }
|
|
|
| +void WebActivity::SetCurrentState(Activity::ActivityState state) {
|
| + switch (state) {
|
| + case ACTIVITY_VISIBLE:
|
| + // Fall through (for the moment).
|
| + case ACTIVITY_INVISIBLE:
|
| + // By clearing the overview mode image we allow the content to be shown.
|
| + overview_mode_image_ = gfx::ImageSkia();
|
| + if (web_view_->IsContentEvicted()) {
|
| + DCHECK_EQ(ACTIVITY_UNLOADED, current_state_);
|
| + web_view_->ReloadContent();
|
| + }
|
| + Observe(web_view_->GetWebContents());
|
| + 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. As soon as the new resource management is
|
| + // agreed upon - or remove otherwise.
|
| + break;
|
| + case ACTIVITY_UNLOADED:
|
| + DCHECK_NE(ACTIVITY_UNLOADED, current_state_);
|
| + Observe(NULL);
|
| + web_view_->EvictContent();
|
| + break;
|
| + }
|
| + // Remember the last requested state.
|
| + current_state_ = state;
|
| +}
|
| +
|
| +Activity::ActivityState WebActivity::GetCurrentState() {
|
| + if (!web_view_ || web_view_->IsContentEvicted()) {
|
| + 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).
|
| +
|
| + return current_state_;
|
| +}
|
| +
|
| +bool WebActivity::IsVisible() {
|
| + return web_view_ && web_view_->IsDrawn();
|
| +}
|
| +
|
| +Activity::ActivityMediaState WebActivity::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;
|
| +}
|
| +
|
| void WebActivity::Init() {
|
| DCHECK(web_view_);
|
| - static_cast<AthenaWebView*>(web_view_)->InstallAccelerators();
|
| + web_view_->InstallAccelerators();
|
| }
|
|
|
| SkColor WebActivity::GetRepresentativeColor() const {
|
| @@ -184,11 +290,21 @@ views::View* WebActivity::GetContentsView() {
|
| if (!web_view_) {
|
| web_view_ = new AthenaWebView(browser_context_);
|
| web_view_->LoadInitialURL(url_);
|
| - Observe(web_view_->GetWebContents());
|
| + SetCurrentState(ACTIVITY_INVISIBLE);
|
| + // Reset the overview mode image.
|
| + overview_mode_image_ = gfx::ImageSkia();
|
| }
|
| return web_view_;
|
| }
|
|
|
| +void WebActivity::CreateOverviewModeImage() {
|
| + // TODO(skuhne): Create an overview.
|
| +}
|
| +
|
| +gfx::ImageSkia WebActivity::GetOverviewModeImage() {
|
| + return overview_mode_image_;
|
| +}
|
| +
|
| void WebActivity::TitleWasSet(content::NavigationEntry* entry,
|
| bool explicit_set) {
|
| ActivityManager::Get()->UpdateActivity(this);
|
|
|