1 // Copyright (c) 2012 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 "ash/screensaver/screensaver_view.h" 6 7 #include "ash/shell.h" 8 #include "ash/shell_delegate.h" 9 #include "base/bind.h" 10 #include "base/logging.h" 11 #include "content/public/browser/browser_context.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/web_contents.h" 14 #include "ui/aura/root_window.h" 15 #include "ui/gfx/screen.h" 16 #include "ui/views/controls/webview/webview.h" 17 #include "ui/views/layout/fill_layout.h" 18 #include "ui/views/widget/widget.h" 19 20 using content::BrowserThread; 21 22 namespace { 23 24 ash::internal::ScreensaverView* g_instance = NULL; 25 26 // Do not restart the screensaver again if it has 27 // terminated kMaxTerminations times already. 28 const int kMaxTerminations = 3; 29 30 } // namespace 31 32 namespace ash { 33 34 void ShowScreensaver(const GURL& url) { 35 internal::ScreensaverView::ShowScreensaver(url); 36 } 37 38 void CloseScreensaver() { 39 internal::ScreensaverView::CloseScreensaver(); 40 } 41 42 bool IsScreensaverShown() { 43 return internal::ScreensaverView::IsScreensaverShown(); 44 } 45 46 namespace internal { 47 48 // static 49 void ScreensaverView::ShowScreensaver(const GURL& url) { 50 if (!g_instance) { 51 g_instance = new ScreensaverView(url); 52 g_instance->Show(); 53 } 54 } 55 56 // static 57 void ScreensaverView::CloseScreensaver() { 58 if (g_instance) { 59 g_instance->Close(); 60 g_instance = NULL; 61 } 62 } 63 64 // static 65 bool ScreensaverView::IsScreensaverShown() { 66 return g_instance && g_instance->IsScreensaverShowingURL(g_instance->url_); 67 } 68 69 bool ScreensaverView::IsScreensaverShowingURL(const GURL& url) { 70 return screensaver_webview_ && 71 screensaver_webview_->web_contents() && 72 (screensaver_webview_->web_contents()->GetURL() == url); 73 } 74 75 //////////////////////////////////////////////////////////////////////////////// 76 // ScreensaverView, views::WidgetDelegateView implementation. 77 views::View* ScreensaverView::GetContentsView() { 78 return this; 79 } 80 81 //////////////////////////////////////////////////////////////////////////////// 82 // ScreensaverView, content::WebContentsObserver implementation. 83 void ScreensaverView::RenderProcessGone( 84 base::TerminationStatus status) { 85 LOG(ERROR) << "Screensaver terminated with status " << status; 86 termination_count_++; 87 88 if (termination_count_ < kMaxTerminations) { 89 LOG(ERROR) << termination_count_ 90 << " terminations is under the threshold of " 91 << kMaxTerminations 92 << "; reloading Screensaver."; 93 LoadScreensaver(); 94 } else { 95 LOG(ERROR) << "Exceeded termination threshold, closing Screensaver."; 96 ScreensaverView::CloseScreensaver(); 97 } 98 } 99 100 //////////////////////////////////////////////////////////////////////////////// 101 // ScreensaverView private methods. 102 ScreensaverView::ScreensaverView(const GURL& url) 103 : url_(url), 104 termination_count_(0), 105 screensaver_webview_(NULL), 106 container_window_(NULL) { 107 } 108 109 ScreensaverView::~ScreensaverView() { 110 } 111 112 void ScreensaverView::Show() { 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 114 // Add the WebView to our view. 115 AddChildWebContents(); 116 // Show the window. 117 ShowWindow(); 118 } 119 120 void ScreensaverView::Close() { 121 DCHECK(GetWidget()); 122 GetWidget()->Close(); 123 } 124 125 void ScreensaverView::AddChildWebContents() { 126 content::BrowserContext* context = 127 Shell::GetInstance()->delegate()->GetActiveBrowserContext(); 128 screensaver_webview_ = new views::WebView(context); 129 SetLayoutManager(new views::FillLayout); 130 AddChildView(screensaver_webview_); 131 132 LoadScreensaver(); 133 content::WebContentsObserver::Observe( 134 screensaver_webview_->GetWebContents()); 135 } 136 137 void ScreensaverView::LoadScreensaver() { 138 screensaver_webview_->GetWebContents()->GetController().LoadURL( 139 url_, 140 content::Referrer(), 141 content::PAGE_TRANSITION_AUTO_TOPLEVEL, 142 std::string()); 143 } 144 145 void ScreensaverView::ShowWindow() { 146 aura::Window* root_window = ash::Shell::GetPrimaryRootWindow(); 147 gfx::Rect screen_rect = 148 Shell::GetScreen()->GetDisplayNearestWindow(root_window).bounds(); 149 150 // We want to be the fullscreen topmost child of the root window. 151 // There should be nothing ever really that should show up on top of us. 152 container_window_ = new views::Widget(); 153 views::Widget::InitParams params( 154 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 155 params.delegate = this; 156 params.parent = root_window; 157 container_window_->Init(params); 158 159 container_window_->StackAtTop(); 160 container_window_->SetBounds(screen_rect); 161 container_window_->Show(); 162 } 163 164 // static 165 ScreensaverView* ScreensaverView::GetInstance() { 166 return g_instance; 167 } 168 169 } // namespace internal 170 } // namespace ash 171