1 // Copyright 2013 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.
5 #include "apps/shell/browser/shell_browser_main_parts.h"
7 #include "apps/shell/browser/shell_browser_context.h"
8 #include "apps/shell/browser/shell_extension_system.h"
9 #include "apps/shell/browser/shell_extension_system_factory.h"
10 #include "apps/shell/browser/shell_extensions_browser_client.h"
11 #include "apps/shell/browser/web_view_window.h"
12 #include "apps/shell/common/shell_extensions_client.h"
13 #include "base/command_line.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/run_loop.h"
17 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
18 #include "content/public/common/result_codes.h"
19 #include "content/shell/browser/shell_devtools_delegate.h"
20 #include "content/shell/browser/shell_net_log.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/browser/renderer_startup_helper.h"
23 #include "ui/aura/env.h"
24 #include "ui/aura/root_window.h"
25 #include "ui/aura/test/test_screen.h"
26 #include "ui/base/ime/input_method_initializer.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/screen.h"
29 #include "ui/views/test/test_views_delegate.h"
30 #include "ui/views/views_delegate.h"
31 #include "ui/views/widget/widget.h"
32 #include "ui/wm/test/wm_test_helper.h"
34 using content::BrowserContext;
35 using extensions::Extension;
36 using extensions::ExtensionSystem;
37 using extensions::ShellExtensionSystem;
42 // Register additional BrowserContextKeyedService factories here. See
43 // ChromeBrowserMainExtraPartsProfiles for details.
44 void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
45 extensions::RendererStartupHelperFactory::GetInstance();
46 extensions::ShellExtensionSystemFactory::GetInstance();
49 // A ViewsDelegate to attach new unparented windows to app_shell's root window.
50 class ShellViewsDelegate : public views::TestViewsDelegate {
52 explicit ShellViewsDelegate(aura::Window* root_window)
53 : root_window_(root_window) {}
54 virtual ~ShellViewsDelegate() {}
56 // views::ViewsDelegate implementation.
57 virtual void OnBeforeWidgetInit(
58 views::Widget::InitParams* params,
59 views::internal::NativeWidgetDelegate* delegate) OVERRIDE {
61 params->parent = root_window_;
65 aura::Window* root_window_;
67 DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegate);
72 ShellBrowserMainParts::ShellBrowserMainParts(
73 const content::MainFunctionParams& parameters)
74 : extension_system_(NULL) {
77 ShellBrowserMainParts::~ShellBrowserMainParts() {
80 void ShellBrowserMainParts::PreMainMessageLoopStart() {
81 // TODO(jamescook): Initialize touch here?
84 void ShellBrowserMainParts::PostMainMessageLoopStart() {
87 void ShellBrowserMainParts::PreEarlyInitialization() {
90 int ShellBrowserMainParts::PreCreateThreads() {
91 // TODO(jamescook): Initialize chromeos::CrosSettings here?
97 void ShellBrowserMainParts::PreMainMessageLoopRun() {
98 // NOTE: Much of this is culled from chrome/test/base/chrome_test_suite.cc
100 // TODO(jamescook): Initialize chromeos::UserManager.
102 net_log_.reset(new content::ShellNetLog("app_shell"));
104 // Initialize our "profile" equivalent.
105 browser_context_.reset(new ShellBrowserContext);
107 extensions_client_.reset(new ShellExtensionsClient());
108 extensions::ExtensionsClient::Set(extensions_client_.get());
110 extensions_browser_client_.reset(
111 new extensions::ShellExtensionsBrowserClient(browser_context_.get()));
112 extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get());
114 // Create our custom ExtensionSystem first because other
115 // BrowserContextKeyedServices depend on it.
116 // TODO(yoz): Move this after EnsureBrowserContextKeyedServiceFactoriesBuilt.
117 CreateExtensionSystem();
119 EnsureBrowserContextKeyedServiceFactoriesBuilt();
120 BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
121 browser_context_.get());
123 devtools_delegate_.reset(
124 new content::ShellDevToolsDelegate(browser_context_.get()));
127 CreateViewsDelegate();
129 const std::string kAppSwitch = "app";
130 CommandLine* command_line = CommandLine::ForCurrentProcess();
131 if (command_line->HasSwitch(kAppSwitch)) {
132 base::FilePath app_dir(command_line->GetSwitchValueNative(kAppSwitch));
133 base::FilePath app_absolute_dir = base::MakeAbsoluteFilePath(app_dir);
134 extension_system_->LoadAndLaunchApp(app_absolute_dir);
136 // TODO(jamescook): For demo purposes create a window with a WebView just
137 // to ensure that the content module is properly initialized.
138 webview_window_.reset(CreateWebViewWindow(browser_context_.get(),
139 wm_test_helper_->root_window()->window()));
140 webview_window_->Show();
144 bool ShellBrowserMainParts::MainMessageLoopRun(int* result_code) {
145 base::RunLoop run_loop;
147 *result_code = content::RESULT_CODE_NORMAL_EXIT;
151 void ShellBrowserMainParts::PostMainMessageLoopRun() {
152 devtools_delegate_->Stop();
153 DestroyViewsDelegate();
155 BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
156 browser_context_.get());
157 extension_system_ = NULL;
158 extensions::ExtensionsBrowserClient::Set(NULL);
159 extensions_browser_client_.reset();
160 browser_context_.reset();
161 aura::Env::DeleteInstance();
164 void ShellBrowserMainParts::OnWindowTreeHostCloseRequested(
165 const aura::RootWindow* root) {
166 base::MessageLoop::current()->PostTask(FROM_HERE,
167 base::MessageLoop::QuitClosure());
170 void ShellBrowserMainParts::CreateRootWindow() {
171 test_screen_.reset(aura::TestScreen::Create());
172 // TODO(jamescook): Replace this with a real Screen implementation.
173 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
174 // TODO(jamescook): Initialize a real input method.
175 ui::InitializeInputMethodForTesting();
176 // Set up basic pieces of views::corewm.
177 wm_test_helper_.reset(new wm::WMTestHelper(gfx::Size(800, 600)));
178 // Ensure the X window gets mapped.
179 wm_test_helper_->root_window()->host()->Show();
180 // Watch for the user clicking the close box.
181 wm_test_helper_->root_window()->AddRootWindowObserver(this);
184 void ShellBrowserMainParts::DestroyRootWindow() {
185 // We should close widget before destroying root window.
186 webview_window_.reset();
187 wm_test_helper_->root_window()->RemoveRootWindowObserver(this);
188 wm_test_helper_->root_window()->PrepareForShutdown();
189 wm_test_helper_.reset();
190 ui::ShutdownInputMethodForTesting();
193 void ShellBrowserMainParts::CreateViewsDelegate() {
194 DCHECK(!views::ViewsDelegate::views_delegate);
195 views::ViewsDelegate::views_delegate =
196 new ShellViewsDelegate(wm_test_helper_->root_window()->window());
199 void ShellBrowserMainParts::DestroyViewsDelegate() {
200 delete views::ViewsDelegate::views_delegate;
201 views::ViewsDelegate::views_delegate = NULL;
204 void ShellBrowserMainParts::CreateExtensionSystem() {
205 DCHECK(browser_context_);
206 extension_system_ = static_cast<ShellExtensionSystem*>(
207 ExtensionSystem::Get(browser_context_.get()));
208 extension_system_->InitForRegularProfile(true);