summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-04 21:38:17 +0000
committerjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-04 21:38:17 +0000
commit0ff151d78683824266581ba161cf361e7f43962c (patch)
tree0b32f3508b43e9dd640dd5dfba309c62f1bd0b51 /apps
parent8069c4e0cac1721e076329252e3d1886dae6ef11 (diff)
downloadchromium_src-0ff151d78683824266581ba161cf361e7f43962c.zip
chromium_src-0ff151d78683824266581ba161cf361e7f43962c.tar.gz
chromium_src-0ff151d78683824266581ba161cf361e7f43962c.tar.bz2
* Add --new-app-window flag to app_shell.
* Add ShellAppWindowCreateFunction to provide a separate implementation of chrome.app.window.create() and manually register it (it has no IDL/JSON representation). * Add ShellAppWindow, a fullscreen app window that has no ui/views dependencies. * Hook up the various extension function dispatch machinery. This helps eliminate //chrome dependencies from app_shell by eliminating dependencies on //apps. BUG=360130 TEST=manual, app_shell --new-app-window can load and display hello-world and calculator NOTRY=true (try servers have no coverage for app_shell yet - we're working on it) Review URL: https://codereview.chromium.org/224733006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261883 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'apps')
-rw-r--r--apps/shell/app_shell.gyp4
-rw-r--r--apps/shell/browser/shell_app_window.cc76
-rw-r--r--apps/shell/browser/shell_app_window.h76
-rw-r--r--apps/shell/browser/shell_app_window_api.cc83
-rw-r--r--apps/shell/browser/shell_app_window_api.h31
-rw-r--r--apps/shell/browser/shell_browser_main_parts.cc1
-rw-r--r--apps/shell/browser/shell_desktop_controller.cc74
-rw-r--r--apps/shell/browser/shell_desktop_controller.h21
-rw-r--r--apps/shell/browser/shell_extensions_browser_client.cc14
9 files changed, 377 insertions, 3 deletions
diff --git a/apps/shell/app_shell.gyp b/apps/shell/app_shell.gyp
index a66c960e..9b5d7e2 100644
--- a/apps/shell/app_shell.gyp
+++ b/apps/shell/app_shell.gyp
@@ -93,6 +93,10 @@
'app/shell_main_delegate.h',
'browser/shell_app_sorting.cc',
'browser/shell_app_sorting.h',
+ 'browser/shell_app_window.cc',
+ 'browser/shell_app_window.h',
+ 'browser/shell_app_window_api.cc',
+ 'browser/shell_app_window_api.h',
'browser/shell_app_window_delegate.cc',
'browser/shell_app_window_delegate.h',
'browser/shell_apps_client.cc',
diff --git a/apps/shell/browser/shell_app_window.cc b/apps/shell/browser/shell_app_window.cc
new file mode 100644
index 0000000..52b1f6a
--- /dev/null
+++ b/apps/shell/browser/shell_app_window.cc
@@ -0,0 +1,76 @@
+// 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 "apps/shell/browser/shell_app_window.h"
+
+#include "apps/shell/browser/shell_extension_web_contents_observer.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
+#include "extensions/browser/view_type_utils.h"
+#include "extensions/common/extension_messages.h"
+#include "ipc/ipc_message_macros.h"
+
+using content::BrowserContext;
+using content::WebContents;
+
+namespace apps {
+
+ShellAppWindow::ShellAppWindow() {}
+
+ShellAppWindow::~ShellAppWindow() {}
+
+void ShellAppWindow::Init(BrowserContext* context, gfx::Size initial_size) {
+ extension_function_dispatcher_.reset(
+ new extensions::ExtensionFunctionDispatcher(context, this));
+
+ // Create the web contents with an initial size to avoid a resize.
+ WebContents::CreateParams create_params(context);
+ create_params.initial_size = initial_size;
+ web_contents_.reset(WebContents::Create(create_params));
+
+ content::WebContentsObserver::Observe(web_contents_.get());
+
+ // Add support for extension startup.
+ extensions::ShellExtensionWebContentsObserver::CreateForWebContents(
+ web_contents_.get());
+
+ extensions::SetViewType(web_contents_.get(),
+ extensions::VIEW_TYPE_APP_WINDOW);
+}
+
+void ShellAppWindow::LoadURL(const GURL& url) {
+ content::NavigationController::LoadURLParams params(url);
+ web_contents_->GetController().LoadURLWithParams(params);
+ web_contents_->GetView()->Focus();
+}
+
+aura::Window* ShellAppWindow::GetNativeWindow() {
+ return web_contents_->GetView()->GetNativeView();
+}
+
+int ShellAppWindow::GetRenderViewRoutingID() {
+ return web_contents_->GetRenderViewHost()->GetRoutingID();
+}
+
+bool ShellAppWindow::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ShellAppWindow, message)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+content::WebContents* ShellAppWindow::GetAssociatedWebContents() const {
+ return web_contents_.get();
+}
+
+void ShellAppWindow::OnRequest(const ExtensionHostMsg_Request_Params& params) {
+ extension_function_dispatcher_->Dispatch(params,
+ web_contents_->GetRenderViewHost());
+}
+
+} // namespace apps
diff --git a/apps/shell/browser/shell_app_window.h b/apps/shell/browser/shell_app_window.h
new file mode 100644
index 0000000..3df66ad
--- /dev/null
+++ b/apps/shell/browser/shell_app_window.h
@@ -0,0 +1,76 @@
+// 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.
+
+#ifndef APPS_SHELL_BROWSER_SHELL_APP_WINDOW_H_
+#define APPS_SHELL_BROWSER_SHELL_APP_WINDOW_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "extensions/browser/extension_function_dispatcher.h"
+
+struct ExtensionHostMsg_Request_Params;
+class GURL;
+
+namespace aura {
+class Window;
+}
+
+namespace content {
+class BrowserContext;
+class WebContents;
+}
+
+namespace extensions {
+class ExtensionFunctionDispatcher;
+}
+
+namespace gfx {
+class Size;
+}
+
+namespace apps {
+
+// A simplified app window created by chrome.app.window.create(). Manages the
+// primary web contents for the app.
+class ShellAppWindow
+ : public content::WebContentsObserver,
+ public extensions::ExtensionFunctionDispatcher::Delegate {
+ public:
+ ShellAppWindow();
+ virtual ~ShellAppWindow();
+
+ // Creates the web contents and attaches extension-specific helpers.
+ // Passing a valid |initial_size| to avoid a web contents resize.
+ void Init(content::BrowserContext* context, gfx::Size initial_size);
+
+ // Starts loading |url| which must be an extension URL.
+ void LoadURL(const GURL& url);
+
+ // Returns the window hosting the web contents.
+ aura::Window* GetNativeWindow();
+
+ // Returns the routing ID of the render view host of |web_contents_|.
+ int GetRenderViewRoutingID();
+
+ // content::WebContentsObserver implementation
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ // extensions::ExtensionFunctionDispatcher::Delegate implementation
+ virtual content::WebContents* GetAssociatedWebContents() const OVERRIDE;
+
+ private:
+ // IPC handler.
+ void OnRequest(const ExtensionHostMsg_Request_Params& params);
+
+ scoped_ptr<content::WebContents> web_contents_;
+ scoped_ptr<extensions::ExtensionFunctionDispatcher>
+ extension_function_dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellAppWindow);
+};
+
+} // namespace apps
+
+#endif // APPS_SHELL_BROWSER_SHELL_APP_WINDOW_H_
diff --git a/apps/shell/browser/shell_app_window_api.cc b/apps/shell/browser/shell_app_window_api.cc
new file mode 100644
index 0000000..136a0ce
--- /dev/null
+++ b/apps/shell/browser/shell_app_window_api.cc
@@ -0,0 +1,83 @@
+// 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 "apps/shell/browser/shell_app_window_api.h"
+
+#include "apps/shell/browser/shell_app_window.h"
+#include "apps/shell/browser/shell_desktop_controller.h"
+#include "base/values.h"
+
+using base::DictionaryValue;
+
+namespace extensions {
+namespace {
+
+// Returns stub values for window bounds.
+DictionaryValue* CreateStubBoundsProperties() {
+ DictionaryValue* properties = new DictionaryValue;
+ properties->SetInteger("left", 0);
+ properties->SetInteger("top", 0);
+ properties->SetInteger("width", 0);
+ properties->SetInteger("height", 0);
+ return properties;
+}
+
+// Creates a function call result to send to the renderer.
+DictionaryValue* CreateResult(apps::ShellAppWindow* app_window) {
+ int view_id = app_window->GetRenderViewRoutingID();
+
+ DictionaryValue* result = new DictionaryValue;
+ result->Set("viewId", new base::FundamentalValue(view_id));
+ result->Set("injectTitlebar", new base::FundamentalValue(false));
+ result->Set("id", new base::StringValue("app_shell"));
+
+ // Add stub window property data.
+ result->SetBoolean("fullscreen", true);
+ result->SetBoolean("minimized", false);
+ result->SetBoolean("maximized", false);
+ result->SetBoolean("alwaysOnTop", false);
+ result->SetBoolean("hasFrameColor", false);
+ result->SetInteger("frameColor", 0);
+ result->Set("innerBounds", CreateStubBoundsProperties());
+ result->Set("outerBounds", CreateStubBoundsProperties());
+
+ return result;
+}
+
+} // namespace
+
+ShellAppWindowCreateFunction::ShellAppWindowCreateFunction() {}
+
+ShellAppWindowCreateFunction::~ShellAppWindowCreateFunction() {}
+
+bool ShellAppWindowCreateFunction::RunImpl() {
+ // Arguments must contain a URL and may contain options and a callback.
+ if (args_->GetSize() < 1 || args_->GetSize() > 3)
+ return false;
+
+ // Extract the URL for the window contents, e.g. "main.html".
+ std::string url_string;
+ if (!args_->GetString(0, &url_string))
+ return false;
+
+ // Convert "main.html" to "chrome-extension:/<id>/main.html".
+ GURL url = GetExtension()->GetResourceURL(url_string);
+ if (!url.is_valid())
+ return false;
+
+ // The desktop keeps ownership of the window.
+ apps::ShellAppWindow* app_window =
+ apps::ShellDesktopController::instance()->CreateAppWindow(
+ browser_context());
+ app_window->LoadURL(url);
+
+ // Create the reply to send to the renderer.
+ DictionaryValue* result = CreateResult(app_window);
+ SetResult(result);
+
+ SendResponse(true /* success */);
+ return true;
+}
+
+} // namespace extensions
diff --git a/apps/shell/browser/shell_app_window_api.h b/apps/shell/browser/shell_app_window_api.h
new file mode 100644
index 0000000..d805dff
--- /dev/null
+++ b/apps/shell/browser/shell_app_window_api.h
@@ -0,0 +1,31 @@
+// 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.
+
+#ifndef APPS_SHELL_BROWSER_SHELL_APP_WINDOW_API_H_
+#define APPS_SHELL_BROWSER_SHELL_APP_WINDOW_API_H_
+
+#include "base/compiler_specific.h"
+#include "extensions/browser/extension_function.h"
+
+namespace extensions {
+
+// A simplified implementation of the chrome.app.window.create() function for
+// app_shell. Opens a fullscreen window and invokes the window callback. Most
+// of the response is stub data, but the JS contentWindow is valid.
+class ShellAppWindowCreateFunction : public UIThreadExtensionFunction {
+ public:
+ ShellAppWindowCreateFunction();
+
+ // Don't use the APP_WINDOW_CREATE histogram so we don't pollute the
+ // statistics for the real Chrome implementation.
+ DECLARE_EXTENSION_FUNCTION("app.window.create", UNKNOWN);
+
+ private:
+ virtual ~ShellAppWindowCreateFunction();
+ virtual bool RunImpl() OVERRIDE;
+};
+
+} // namespace extensions
+
+#endif // APPS_SHELL_BROWSER_SHELL_APP_WINDOW_API_H_
diff --git a/apps/shell/browser/shell_browser_main_parts.cc b/apps/shell/browser/shell_browser_main_parts.cc
index 2700cb4..b375e6c 100644
--- a/apps/shell/browser/shell_browser_main_parts.cc
+++ b/apps/shell/browser/shell_browser_main_parts.cc
@@ -143,6 +143,7 @@ void ShellBrowserMainParts::PostMainMessageLoopRun() {
void ShellBrowserMainParts::OnHostCloseRequested(
const aura::WindowTreeHost* host) {
+ desktop_controller_->CloseAppWindow();
extension_system_->CloseApp();
base::MessageLoop::current()->PostTask(FROM_HERE,
base::MessageLoop::QuitClosure());
diff --git a/apps/shell/browser/shell_desktop_controller.cc b/apps/shell/browser/shell_desktop_controller.cc
index 9725c51..373b881 100644
--- a/apps/shell/browser/shell_desktop_controller.cc
+++ b/apps/shell/browser/shell_desktop_controller.cc
@@ -4,9 +4,12 @@
#include "apps/shell/browser/shell_desktop_controller.h"
+#include "apps/shell/browser/shell_app_window.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/env.h"
+#include "ui/aura/layout_manager.h"
#include "ui/aura/test/test_screen.h"
+#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/ime/input_method_initializer.h"
#include "ui/gfx/screen.h"
@@ -25,6 +28,40 @@ namespace {
const SkColor kBackgroundColor = SK_ColorBLACK;
+// A simple layout manager that makes each new window fill its parent.
+class FillLayout : public aura::LayoutManager {
+ public:
+ FillLayout() {}
+ virtual ~FillLayout() {}
+
+ private:
+ // aura::LayoutManager:
+ virtual void OnWindowResized() OVERRIDE {}
+
+ virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
+ if (!child->parent())
+ return;
+
+ // Create a rect at 0,0 with the size of the parent.
+ gfx::Size parent_size = child->parent()->bounds().size();
+ child->SetBounds(gfx::Rect(parent_size));
+ }
+
+ virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
+
+ virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
+
+ virtual void OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) OVERRIDE {}
+
+ virtual void SetChildBounds(aura::Window* child,
+ const gfx::Rect& requested_bounds) OVERRIDE {
+ SetChildBoundsDirect(child, requested_bounds);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(FillLayout);
+};
+
// A ViewsDelegate to attach new unparented windows to app_shell's root window.
class ShellViewsDelegate : public views::TestViewsDelegate {
public:
@@ -46,6 +83,8 @@ class ShellViewsDelegate : public views::TestViewsDelegate {
DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegate);
};
+ShellDesktopController* g_instance = NULL;
+
} // namespace
ShellDesktopController::ShellDesktopController() {
@@ -60,15 +99,42 @@ ShellDesktopController::ShellDesktopController() {
DCHECK(!views::ViewsDelegate::views_delegate);
views::ViewsDelegate::views_delegate =
new ShellViewsDelegate(wm_test_helper_->host()->window());
+
+ g_instance = this;
}
ShellDesktopController::~ShellDesktopController() {
+ // The app window must be explicitly closed before desktop teardown.
+ DCHECK(!app_window_);
+ g_instance = NULL;
delete views::ViewsDelegate::views_delegate;
views::ViewsDelegate::views_delegate = NULL;
DestroyRootWindow();
aura::Env::DeleteInstance();
}
+// static
+ShellDesktopController* ShellDesktopController::instance() {
+ return g_instance;
+}
+
+ShellAppWindow* ShellDesktopController::CreateAppWindow(
+ content::BrowserContext* context) {
+ aura::Window* root_window = GetWindowTreeHost()->window();
+
+ app_window_.reset(new ShellAppWindow);
+ app_window_->Init(context, root_window->bounds().size());
+
+ // Attach the web contents view to our window hierarchy.
+ aura::Window* content = app_window_->GetNativeWindow();
+ root_window->AddChild(content);
+ content->Show();
+
+ return app_window_.get();
+}
+
+void ShellDesktopController::CloseAppWindow() { app_window_.reset(); }
+
aura::WindowTreeHost* ShellDesktopController::GetWindowTreeHost() {
return wm_test_helper_->host();
}
@@ -94,10 +160,14 @@ void ShellDesktopController::CreateRootWindow() {
if (size.IsEmpty())
size = gfx::Size(800, 600);
wm_test_helper_.reset(new wm::WMTestHelper(size));
- wm_test_helper_->host()->compositor()->SetBackgroundColor(kBackgroundColor);
+ aura::WindowTreeHost* host = wm_test_helper_->host();
+ host->compositor()->SetBackgroundColor(kBackgroundColor);
+
+ // Ensure new windows fill the display.
+ host->window()->SetLayoutManager(new FillLayout);
// Ensure the X window gets mapped.
- wm_test_helper_->host()->Show();
+ host->Show();
}
void ShellDesktopController::DestroyRootWindow() {
diff --git a/apps/shell/browser/shell_desktop_controller.h b/apps/shell/browser/shell_desktop_controller.h
index 3420790..1dcf503 100644
--- a/apps/shell/browser/shell_desktop_controller.h
+++ b/apps/shell/browser/shell_desktop_controller.h
@@ -20,12 +20,18 @@ class TestScreen;
class WindowTreeHost;
}
+namespace content {
+class BrowserContext;
+}
+
namespace wm {
class WMTestHelper;
}
namespace apps {
+class ShellAppWindow;
+
// Handles desktop-related tasks for app_shell.
class ShellDesktopController
#if defined(OS_CHROMEOS)
@@ -36,6 +42,18 @@ class ShellDesktopController
ShellDesktopController();
virtual ~ShellDesktopController();
+ // Returns the single instance of the desktop. (Stateless functions like
+ // ShellAppWindowCreateFunction need to be able to access the desktop, so
+ // we need a singleton somewhere).
+ static ShellDesktopController* instance();
+
+ // Creates a new app window and adds it to the desktop. The desktop maintains
+ // ownership of the window.
+ ShellAppWindow* CreateAppWindow(content::BrowserContext* context);
+
+ // Closes and destroys the app window.
+ void CloseAppWindow();
+
// Returns the host for the Aura window tree.
aura::WindowTreeHost* GetWindowTreeHost();
@@ -66,6 +84,9 @@ class ShellDesktopController
scoped_ptr<aura::TestScreen> test_screen_;
+ // The desktop supports a single app window.
+ scoped_ptr<ShellAppWindow> app_window_;
+
DISALLOW_COPY_AND_ASSIGN(ShellDesktopController);
};
diff --git a/apps/shell/browser/shell_extensions_browser_client.cc b/apps/shell/browser/shell_extensions_browser_client.cc
index 9207f77..91a7e6c 100644
--- a/apps/shell/browser/shell_extensions_browser_client.cc
+++ b/apps/shell/browser/shell_extensions_browser_client.cc
@@ -6,8 +6,10 @@
#include "apps/common/api/generated_api.h"
#include "apps/shell/browser/shell_app_sorting.h"
+#include "apps/shell/browser/shell_app_window_api.h"
#include "apps/shell/browser/shell_extension_system_factory.h"
#include "apps/shell/browser/shell_extension_web_contents_observer.h"
+#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/pref_service_factory.h"
#include "base/prefs/testing_pref_store.h"
@@ -16,6 +18,7 @@
#include "components/user_prefs/user_prefs.h"
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/app_sorting.h"
+#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_host_delegate.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/api/generated_api.h"
@@ -204,8 +207,17 @@ void ShellExtensionsBrowserClient::RegisterExtensionFunctions(
apps::api::GeneratedFunctionRegistry::RegisterAll(registry);
// TODO(rockot): Remove dependency on src/chrome once we have some core APIs
- // moved out. See http://crbug.com/349042.
+ // moved out. Also clean up the comment below. See http://crbug.com/349042.
extensions::api::GeneratedFunctionRegistry::RegisterAll(registry);
+
+ // Register our simplified implementation for chrome.app.window.create().
+ // By registering it after extensions::api::GeneratedFunctionRegistry above
+ // we override the Chrome version of this function.
+ // TODO(jamescook): Remove the switch when the simple window good enough to
+ // use by default.
+ const std::string kNewAppWindow = "new-app-window";
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(kNewAppWindow))
+ registry->RegisterFunction<ShellAppWindowCreateFunction>();
}
} // namespace extensions