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