diff options
34 files changed, 583 insertions, 35 deletions
diff --git a/apps/shell/DEPS b/apps/shell/DEPS index 66f0b37..8a9dc71 100644 --- a/apps/shell/DEPS +++ b/apps/shell/DEPS @@ -7,15 +7,18 @@ include_rules = [ "+apps/shell/common", "+apps/shell/test", + # Do not add dependencies on Chrome. Talk to OWNERS about how to refactor + # the code you need to a shared location. + "-chrome", + + # Only allow app_shell and extensions resources, not general Chrome ones. + "-grit", + "+grit/app_shell_resources.h", "+grit/extensions_resources.h", # TODO(yoz): Do not depend on Chrome resources. "!grit/common_resources.h", - # Do not add dependencies on Chrome. Talk to OWNERS about how to refactor - # the code you need to a shared location. - "-chrome", - # Real DEPS go in subdirectories, for example apps/shell/browser/DEPS. # Temporary exceptions for app_shell bring-up go here. # TODO(jamescook): Remove these. http://crbug.com/305404 @@ -25,4 +28,5 @@ include_rules = [ "!chrome/common/extensions/permissions/chrome_api_permissions.h", "!chrome/renderer/extensions/dispatcher.h", "!chrome/renderer/extensions/extension_helper.h", + "!chrome/renderer/resource_bundle_source_map.h", ] diff --git a/apps/shell/app_shell.gyp b/apps/shell/app_shell.gyp index 3e09a8f..f655b62 100644 --- a/apps/shell/app_shell.gyp +++ b/apps/shell/app_shell.gyp @@ -8,9 +8,24 @@ }, 'targets': [ { + 'target_name': 'app_shell_resources', + 'type': 'none', + 'actions': [ + { + 'action_name': 'generate_app_shell_resources', + 'variables': { + 'grit_grd_file': 'app_shell_resources.grd', + 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/apps/shell', + }, + 'includes': [ '../../build/grit_action.gypi' ], + }, + ], + }, + { 'target_name': 'app_shell_pak', 'type': 'none', 'dependencies': [ + 'app_shell_resources', # Need extension related resources in common_resources.pak and # renderer_resources_100_percent.pak '<(DEPTH)/chrome/chrome_resources.gyp:chrome_resources', @@ -27,6 +42,7 @@ 'action_name': 'repack_app_shell_pack', 'variables': { 'pak_inputs': [ + '<(SHARED_INTERMEDIATE_DIR)/apps/shell/app_shell_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/chrome/common_resources.pak', '<(SHARED_INTERMEDIATE_DIR)/chrome/extensions_api_resources.pak', # TODO(jamescook): Extract the extension/app related resources @@ -63,6 +79,7 @@ # TODO(rockot): Dependencies above this line are temporary. # See http://crbug.com/359656. 'app_shell_pak', + '<(DEPTH)/apps/shell/common/api/api.gyp:shell_api', '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/base/base.gyp:base_prefs_test_support', '<(DEPTH)/content/content.gyp:content', @@ -84,10 +101,13 @@ 'include_dirs': [ '../..', '<(SHARED_INTERMEDIATE_DIR)', + '<(SHARED_INTERMEDIATE_DIR)/apps/shell', ], 'sources': [ 'app/shell_main_delegate.cc', 'app/shell_main_delegate.h', + 'browser/api/shell/shell_api.cc', + 'browser/api/shell/shell_api.h', 'browser/shell_app_runtime_api.cc', 'browser/shell_app_runtime_api.h', 'browser/shell_app_sorting.cc', @@ -120,6 +140,9 @@ 'common/shell_extensions_client.h', 'renderer/shell_content_renderer_client.cc', 'renderer/shell_content_renderer_client.h', + 'renderer/shell_custom_bindings.cc', + 'renderer/shell_custom_bindings.h', + 'renderer/shell_custom_bindings.js', 'renderer/shell_extensions_renderer_client.cc', 'renderer/shell_extensions_renderer_client.h', ], diff --git a/apps/shell/app_shell_resources.grd b/apps/shell/app_shell_resources.grd new file mode 100644 index 0000000..4e77d0d --- /dev/null +++ b/apps/shell/app_shell_resources.grd @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1"> + <outputs> + <output filename="grit/app_shell_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="app_shell_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <!-- Custom bindings for extension APIs. --> + <include name="IDR_SHELL_CUSTOM_BINDINGS_JS" file="renderer\shell_custom_bindings.js" type="BINDATA" /> + </includes> + </release> +</grit> diff --git a/apps/shell/browser/api/shell/shell_api.cc b/apps/shell/browser/api/shell/shell_api.cc new file mode 100644 index 0000000..929d1db --- /dev/null +++ b/apps/shell/browser/api/shell/shell_api.cc @@ -0,0 +1,62 @@ +// 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/api/shell/shell_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 apps { +namespace { + +// 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)); + return result; +} + +} // namespace + +ShellCreateWindowFunction::ShellCreateWindowFunction() { +} + +ShellCreateWindowFunction::~ShellCreateWindowFunction() { +} + +bool ShellCreateWindowFunction::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 apps diff --git a/apps/shell/browser/api/shell/shell_api.h b/apps/shell/browser/api/shell/shell_api.h new file mode 100644 index 0000000..d7f02eb --- /dev/null +++ b/apps/shell/browser/api/shell/shell_api.h @@ -0,0 +1,33 @@ +// 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_API_SHELL_SHELL_API_H_ +#define APPS_SHELL_BROWSER_API_SHELL_SHELL_API_H_ + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "extensions/browser/extension_function.h" +#include "extensions/browser/extension_function_histogram_value.h" + +namespace apps { + +// Implementation of the chrome.shell.createWindow() function for app_shell. +// Opens a fullscreen window and invokes the window callback to allow access to +// the JS contentWindow. +class ShellCreateWindowFunction : public UIThreadExtensionFunction { + public: + ShellCreateWindowFunction(); + + DECLARE_EXTENSION_FUNCTION("shell.createWindow", SHELL_CREATEWINDOW); + + private: + virtual ~ShellCreateWindowFunction(); + virtual bool RunImpl() OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(ShellCreateWindowFunction); +}; + +} // namespace apps + +#endif // APPS_SHELL_BROWSER_API_SHELL_SHELL_API_H_ diff --git a/apps/shell/browser/shell_extensions_browser_client.cc b/apps/shell/browser/shell_extensions_browser_client.cc index 7dcf741..e84bf09 100644 --- a/apps/shell/browser/shell_extensions_browser_client.cc +++ b/apps/shell/browser/shell_extensions_browser_client.cc @@ -8,6 +8,7 @@ #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 "apps/shell/common/api/generated_api.h" #include "base/prefs/pref_service.h" #include "base/prefs/pref_service_factory.h" #include "base/prefs/testing_pref_store.h" @@ -231,6 +232,9 @@ void ShellExtensionsBrowserClient::RegisterExtensionFunctions( // moved out. Also clean up the comment below. See http://crbug.com/349042. extensions::api::GeneratedFunctionRegistry::RegisterAll(registry); + // Register chrome.shell APIs. + apps::shell_api::GeneratedFunctionRegistry::RegisterAll(registry); + // Register our simplified implementation for chrome.app.window.create(). registry->RegisterFunction<ShellAppWindowCreateFunction>(); } diff --git a/apps/shell/common/api/api.gyp b/apps/shell/common/api/api.gyp new file mode 100644 index 0000000..bbefdb8 --- /dev/null +++ b/apps/shell/common/api/api.gyp @@ -0,0 +1,36 @@ +# 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. + +{ + 'targets': [ + { + 'target_name': 'shell_api', + 'type': 'static_library', + 'sources': [ + '<@(schema_files)', + ], + # TODO(jschuh): http://crbug.com/167187 size_t -> int + 'msvs_disabled_warnings': [ 4267 ], + 'includes': [ + '../../../../build/json_schema_bundle_compile.gypi', + '../../../../build/json_schema_compile.gypi', + ], + 'variables': { + 'chromium_code': 1, + 'non_compiled_schema_files': [ + ], + # TODO: Eliminate these on Android. See crbug.com/305852. + 'schema_files': [ + 'shell.idl', + ], + 'cc_dir': 'apps/shell/common/api', + 'root_namespace': 'apps::shell_api', + 'impl_dir': 'apps/shell/browser/api', + }, + 'dependencies': [ + '<(DEPTH)/skia/skia.gyp:skia', + ], + }, + ], +} diff --git a/apps/shell/common/api/shell.idl b/apps/shell/common/api/shell.idl new file mode 100644 index 0000000..c57512f --- /dev/null +++ b/apps/shell/common/api/shell.idl @@ -0,0 +1,50 @@ +// 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. + +// Use the <code>chrome.shell</code> API to watch for launch events and create +// windows. The <code>createWindow</code> API is a subset of +// <code>chrome.app.window.create</code>. +namespace shell { + + [noinline_doc] dictionary CreateWindowOptions { + // Stub for the id of a window. This parameter is ignored in app_shell but + // provided for compatibility with apps running in Chrome. + DOMString? id; + + // Stubs for the bounds of a window; these parameters are ignored in + // app_shell but are provided for compatibility with apps running in Chrome. + // The created window will always fill the root window of the default + // display. + object? innerBounds; + object? outerBounds; + }; + + // Called in the creating window (parent) before the load event is called in + // the created window (child). The parent can set fields or functions on the + // child usable from onload. E.g. background.js:<br> + // <code>function(createdWindow) { createdWindow.contentWindow.foo = + // function () { }; };</code> + // <br>window.js:<br> + // <code>window.onload = function () { foo(); }</code> + callback CreateWindowCallback = + void ([instanceOf=AppWindow] object createdWindow); + + [noinline_doc] dictionary AppWindow { + // The JavaScript 'window' object for the created child. + [instanceOf=Window] object contentWindow; + }; + + interface Functions { + // Creates a fullscreen window on the default display. Options for id and + // bounds are ignored. + static void createWindow(DOMString url, + optional CreateWindowOptions options, + optional CreateWindowCallback callback); + + // Returns an $(ref:AppWindow) object for the current script context + // (i.e. JavaScript 'window' object). + [nocompile] static AppWindow currentWindow(); + [nocompile, nodoc] static void initializeAppWindow(); + }; +}; diff --git a/apps/shell/common/shell_extensions_client.cc b/apps/shell/common/shell_extensions_client.cc index bd1dc1c..959464c 100644 --- a/apps/shell/common/shell_extensions_client.cc +++ b/apps/shell/common/shell_extensions_client.cc @@ -4,6 +4,7 @@ #include "apps/shell/common/shell_extensions_client.h" +#include "apps/shell/common/api/generated_schemas.h" #include "apps/shell/common/shell_app_runtime.h" #include "base/logging.h" #include "chrome/common/extensions/api/generated_schemas.h" @@ -192,6 +193,7 @@ bool ShellExtensionsClient::IsAPISchemaGenerated( // have the Chrome app APIs available. return extensions::api::GeneratedSchemas::IsGenerated(name) || extensions::core_api::GeneratedSchemas::IsGenerated(name) || + apps::shell_api::GeneratedSchemas::IsGenerated(name) || name == extensions::ShellAppRuntime::GetName(); } @@ -202,7 +204,12 @@ base::StringPiece ShellExtensionsClient::GetAPISchema( if (extensions::api::GeneratedSchemas::IsGenerated(name)) return extensions::api::GeneratedSchemas::Get(name); + // Schema for chrome.shell APIs. + if (apps::shell_api::GeneratedSchemas::IsGenerated(name)) + return apps::shell_api::GeneratedSchemas::Get(name); + // Special-case our simplified app.runtime implementation. + // TODO(jamescook): Move this into a chrome.shell.onLaunched() event. if (name == extensions::ShellAppRuntime::GetName()) return extensions::ShellAppRuntime::GetSchema(); diff --git a/apps/shell/renderer/DEPS b/apps/shell/renderer/DEPS index ad0792d..cd0d5db 100644 --- a/apps/shell/renderer/DEPS +++ b/apps/shell/renderer/DEPS @@ -4,4 +4,7 @@ include_rules = [ "+content/public/common", "+content/public/renderer", "+content/public/test", + + "+third_party/WebKit/public", + "+v8/include", ] diff --git a/apps/shell/renderer/shell_content_renderer_client.cc b/apps/shell/renderer/shell_content_renderer_client.cc index a0dffbd..8c4befd 100644 --- a/apps/shell/renderer/shell_content_renderer_client.cc +++ b/apps/shell/renderer/shell_content_renderer_client.cc @@ -64,17 +64,18 @@ ShellContentRendererClient::~ShellContentRendererClient() {} void ShellContentRendererClient::RenderThreadStarted() { RenderThread* thread = RenderThread::Get(); - extension_dispatcher_.reset(new extensions::Dispatcher()); - thread->AddObserver(extension_dispatcher_.get()); - - // TODO(jamescook): Init WebSecurityPolicy for chrome-extension: schemes. - // See ChromeContentRendererClient for details. - extensions_client_.reset(new ShellExtensionsClient); extensions::ExtensionsClient::Set(extensions_client_.get()); extensions_renderer_client_.reset(new ShellExtensionsRendererClient); extensions::ExtensionsRendererClient::Set(extensions_renderer_client_.get()); + + // Must be initialized after ExtensionsRendererClient. + extension_dispatcher_.reset(new extensions::Dispatcher()); + thread->AddObserver(extension_dispatcher_.get()); + + // TODO(jamescook): Init WebSecurityPolicy for chrome-extension: schemes. + // See ChromeContentRendererClient for details. } void ShellContentRendererClient::RenderFrameCreated( diff --git a/apps/shell/renderer/shell_custom_bindings.cc b/apps/shell/renderer/shell_custom_bindings.cc new file mode 100644 index 0000000..c4101b6 --- /dev/null +++ b/apps/shell/renderer/shell_custom_bindings.cc @@ -0,0 +1,57 @@ +// 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/renderer/shell_custom_bindings.h" + +#include "content/public/renderer/render_thread.h" +#include "content/public/renderer/render_view.h" +#include "content/public/renderer/v8_value_converter.h" +#include "extensions/common/extension_messages.h" +#include "extensions/renderer/script_context.h" +#include "extensions/renderer/script_context_set.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "v8/include/v8.h" + +namespace apps { + +ShellCustomBindings::ShellCustomBindings(extensions::ScriptContext* context) + : extensions::ObjectBackedNativeHandler(context) { + RouteFunction( + "GetView", + base::Bind(&ShellCustomBindings::GetView, base::Unretained(this))); +} + +void ShellCustomBindings::GetView( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsInt32()) + return; + + int view_id = args[0]->Int32Value(); + if (view_id == MSG_ROUTING_NONE) + return; + + content::RenderView* view = content::RenderView::FromRoutingID(view_id); + if (!view) + return; + + // Set the opener so we have a security origin set up before returning the DOM + // reference. + content::RenderView* render_view = context()->GetRenderView(); + if (!render_view) + return; + blink::WebFrame* opener = render_view->GetWebView()->mainFrame(); + blink::WebFrame* frame = view->GetWebView()->mainFrame(); + frame->setOpener(opener); + + // Resume resource requests. + content::RenderThread::Get()->Send( + new ExtensionHostMsg_ResumeRequests(view->GetRoutingID())); + + // Return the script context. + v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global(); + args.GetReturnValue().Set(window); +} + +} // namespace apps diff --git a/apps/shell/renderer/shell_custom_bindings.h b/apps/shell/renderer/shell_custom_bindings.h new file mode 100644 index 0000000..743903d --- /dev/null +++ b/apps/shell/renderer/shell_custom_bindings.h @@ -0,0 +1,25 @@ +// 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_RENDERER_SHELL_CUSTOM_BINDINGS_H_ +#define APPS_SHELL_RENDERER_SHELL_CUSTOM_BINDINGS_H_ + +#include "extensions/renderer/object_backed_native_handler.h" + +namespace apps { + +// Implements custom bindings for the chrome.shell API. +class ShellCustomBindings : public extensions::ObjectBackedNativeHandler { + public: + ShellCustomBindings(extensions::ScriptContext* context); + + private: + void GetView(const v8::FunctionCallbackInfo<v8::Value>& args); + + DISALLOW_COPY_AND_ASSIGN(ShellCustomBindings); +}; + +} // namespace apps + +#endif // APPS_SHELL_RENDERER_SHELL_CUSTOM_BINDINGS_H_ diff --git a/apps/shell/renderer/shell_custom_bindings.js b/apps/shell/renderer/shell_custom_bindings.js new file mode 100644 index 0000000..5fe9a9ae --- /dev/null +++ b/apps/shell/renderer/shell_custom_bindings.js @@ -0,0 +1,78 @@ +// 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. + +var shellNatives = requireNative('shell_natives'); +var Binding = require('binding').Binding; +var forEach = require('utils').forEach; +var renderViewObserverNatives = requireNative('renderViewObserverNatives'); + +var currentAppWindow = null; + +var shell = Binding.create('shell'); +shell.registerCustomHook(function(bindingsAPI) { + var apiFunctions = bindingsAPI.apiFunctions; + + apiFunctions.setCustomCallback('createWindow', + function(name, request, windowParams) { + var view = null; + + // When window creation fails, |windowParams| will be undefined. + if (windowParams && windowParams.viewId) { + view = shellNatives.GetView(windowParams.viewId); + } + + if (!view) { + // No route to created window. If given a callback, trigger it with an + // undefined object. + if (request.callback) { + request.callback(undefined); + delete request.callback; + } + return; + } + + // Initialize the app window in the newly created JS context + view.chrome.shell.initializeAppWindow(); + + var callback = request.callback; + if (callback) { + delete request.callback; + + var willCallback = + renderViewObserverNatives.OnDocumentElementCreated( + windowParams.viewId, + function(success) { + if (success) { + callback(view.chrome.shell.currentWindow()); + } else { + callback(undefined); + } + }); + if (!willCallback) { + callback(undefined); + } + } + }); + + apiFunctions.setHandleRequest('currentWindow', function() { + if (!currentAppWindow) { + console.error( + 'The JavaScript context calling chrome.shell.currentWindow() has' + + ' no associated AppWindow.'); + return null; + } + return currentAppWindow; + }); + + // This is an internal function, but needs to be bound into a closure + // so the correct JS context is used for global variables such as + // currentAppWindow. + apiFunctions.setHandleRequest('initializeAppWindow', function() { + var AppWindow = function() {}; + AppWindow.prototype.contentWindow = window; + currentAppWindow = new AppWindow; + }); +}); + +exports.binding = shell.generate(); diff --git a/apps/shell/renderer/shell_extensions_renderer_client.cc b/apps/shell/renderer/shell_extensions_renderer_client.cc index c5de265..039a970 100644 --- a/apps/shell/renderer/shell_extensions_renderer_client.cc +++ b/apps/shell/renderer/shell_extensions_renderer_client.cc @@ -4,6 +4,12 @@ #include "apps/shell/renderer/shell_extensions_renderer_client.h" +#include "apps/shell/renderer/shell_custom_bindings.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/renderer/resource_bundle_source_map.h" +#include "extensions/renderer/module_system.h" +#include "grit/app_shell_resources.h" + namespace apps { ShellExtensionsRendererClient::ShellExtensionsRendererClient() {} @@ -22,4 +28,17 @@ int ShellExtensionsRendererClient::GetLowestIsolatedWorldId() const { return 1; } +void ShellExtensionsRendererClient::RegisterNativeHandlers( + extensions::ModuleSystem* module_system, + extensions::ScriptContext* context) { + module_system->RegisterNativeHandler( + "shell_natives", + scoped_ptr<extensions::NativeHandler>(new ShellCustomBindings(context))); +} + +void ShellExtensionsRendererClient::PopulateSourceMap( + ResourceBundleSourceMap* source_map) { + source_map->RegisterSource("shell", IDR_SHELL_CUSTOM_BINDINGS_JS); +} + } // namespace apps diff --git a/apps/shell/renderer/shell_extensions_renderer_client.h b/apps/shell/renderer/shell_extensions_renderer_client.h index 7b32f90..e67d875 100644 --- a/apps/shell/renderer/shell_extensions_renderer_client.h +++ b/apps/shell/renderer/shell_extensions_renderer_client.h @@ -19,6 +19,10 @@ class ShellExtensionsRendererClient // extensions::ExtensionsRendererClient implementation. virtual bool IsIncognitoProcess() const OVERRIDE; virtual int GetLowestIsolatedWorldId() const OVERRIDE; + virtual void RegisterNativeHandlers( + extensions::ModuleSystem* module_system, + extensions::ScriptContext* context) OVERRIDE; + virtual void PopulateSourceMap(ResourceBundleSourceMap* source_map) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(ShellExtensionsRendererClient); diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index e1775c4..4592b02 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json @@ -644,6 +644,12 @@ "dependencies": ["permission:sessions"], "contexts": ["blessed_extension"] }, + // TODO(jamescook): Move this to app_shell _api_features.json once that file + // exists. + "shell": { + "contexts": ["blessed_extension"], + "extension_types": ["platform_app"] + }, "signedInDevices": { "dependencies": ["permission:signedInDevices"], "contexts": ["blessed_extension"] diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/controller.js b/chrome/common/extensions/docs/examples/apps/calculator/app/controller.js index 2340249..1441990 100644 --- a/chrome/common/extensions/docs/examples/apps/calculator/app/controller.js +++ b/chrome/common/extensions/docs/examples/apps/calculator/app/controller.js @@ -10,8 +10,12 @@ // in non-Chrome browsers, which is useful for example to test touch support // with a non-Chrome touch device. if (typeof chrome !== 'undefined' && chrome.app && chrome.app.runtime) { + // Compatibility for running under app_shell, which does not have app.window. + var createWindow = + chrome.shell ? chrome.shell.createWindow : chrome.app.window.create; + var showCalculatorWindow = function () { - chrome.app.window.create('calculator.html', { + createWindow('calculator.html', { innerBounds: { width: 243, minWidth: 243, maxWidth: 243, height: 380, minHeight: 380, maxHeight: 380 diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 0bdf8c8..f246fd4 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -226,6 +226,11 @@ bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) { ChromeContentRendererClient::ChromeContentRendererClient() { g_current_client = this; + + extensions::ExtensionsClient::Set( + extensions::ChromeExtensionsClient::GetInstance()); + extensions::ExtensionsRendererClient::Set( + ChromeExtensionsRendererClient::GetInstance()); } ChromeContentRendererClient::~ChromeContentRendererClient() { @@ -236,8 +241,9 @@ void ChromeContentRendererClient::RenderThreadStarted() { RenderThread* thread = RenderThread::Get(); chrome_observer_.reset(new ChromeRenderProcessObserver(this)); + // ChromeRenderViewTest::SetUp() creates its own ExtensionDispatcher and - // injects it using SetExtensionDispatcher(). Don't overwrite it. + // injects it using SetExtensionDispatcherForTest(). Don't overwrite it. if (!extension_dispatcher_) extension_dispatcher_.reset(new extensions::Dispatcher()); permissions_policy_delegate_.reset( @@ -359,11 +365,6 @@ void ChromeContentRendererClient::RenderThreadStarted() { WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy( extension_resource_scheme); - extensions::ExtensionsClient::Set( - extensions::ChromeExtensionsClient::GetInstance()); - extensions::ExtensionsRendererClient::Set( - ChromeExtensionsRendererClient::GetInstance()); - #if defined(OS_WIN) // Report if the renderer process has been patched by chrome_elf. // TODO(csharp): Remove once the renderer is no longer getting @@ -1246,7 +1247,7 @@ bool ChromeContentRendererClient::ShouldOverridePageVisibilityState( return true; } -void ChromeContentRendererClient::SetExtensionDispatcher( +void ChromeContentRendererClient::SetExtensionDispatcherForTest( extensions::Dispatcher* extension_dispatcher) { extension_dispatcher_.reset(extension_dispatcher); permissions_policy_delegate_.reset( @@ -1254,6 +1255,11 @@ void ChromeContentRendererClient::SetExtensionDispatcher( extension_dispatcher_.get())); } +extensions::Dispatcher* +ChromeContentRendererClient::GetExtensionDispatcherForTest() { + return extension_dispatcher_.get(); +} + bool ChromeContentRendererClient::CrossesExtensionExtents( WebFrame* frame, const GURL& new_url, diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 277487f..ba227e3 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h @@ -131,8 +131,10 @@ class ChromeContentRendererClient : public content::ContentRendererClient { virtual void AddKeySystems( std::vector<content::KeySystemInfo>* key_systems) OVERRIDE; - // For testing. - void SetExtensionDispatcher(extensions::Dispatcher* extension_dispatcher); + // Takes ownership. + void SetExtensionDispatcherForTest( + extensions::Dispatcher* extension_dispatcher); + extensions::Dispatcher* GetExtensionDispatcherForTest(); #if defined(ENABLE_SPELLCHECK) // Sets a new |spellcheck|. Used for testing only. diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc index c3ef38d..cd0b732 100644 --- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc +++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc @@ -26,3 +26,12 @@ bool ChromeExtensionsRendererClient::IsIncognitoProcess() const { int ChromeExtensionsRendererClient::GetLowestIsolatedWorldId() const { return chrome::ISOLATED_WORLD_ID_EXTENSIONS; } + +void ChromeExtensionsRendererClient::RegisterNativeHandlers( + extensions::ModuleSystem* module_system, + extensions::ScriptContext* context) { +} + +void ChromeExtensionsRendererClient::PopulateSourceMap( + ResourceBundleSourceMap* source_map) { +} diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.h b/chrome/renderer/extensions/chrome_extensions_renderer_client.h index 801bc1aa..092e52f 100644 --- a/chrome/renderer/extensions/chrome_extensions_renderer_client.h +++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.h @@ -20,6 +20,10 @@ class ChromeExtensionsRendererClient // extensions::ExtensionsRendererClient implementation. virtual bool IsIncognitoProcess() const OVERRIDE; virtual int GetLowestIsolatedWorldId() const OVERRIDE; + virtual void RegisterNativeHandlers( + extensions::ModuleSystem* module_system, + extensions::ScriptContext* context) OVERRIDE; + virtual void PopulateSourceMap(ResourceBundleSourceMap* source_map) OVERRIDE; private: DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsRendererClient); diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc index cd5f443..59311fd 100644 --- a/chrome/renderer/extensions/dispatcher.cc +++ b/chrome/renderer/extensions/dispatcher.cc @@ -72,6 +72,7 @@ #include "extensions/renderer/document_custom_bindings.h" #include "extensions/renderer/event_bindings.h" #include "extensions/renderer/extension_groups.h" +#include "extensions/renderer/extensions_renderer_client.h" #include "extensions/renderer/file_system_natives.h" #include "extensions/renderer/i18n_custom_bindings.h" #include "extensions/renderer/id_generator_custom_bindings.h" @@ -475,6 +476,8 @@ Dispatcher::Dispatcher() user_script_slave_.reset(new UserScriptSlave(&extensions_)); request_sender_.reset(new RequestSender(this)); PopulateSourceMap(); + // Register JS sources from the extensions module embedder. + ExtensionsRendererClient::Get()->PopulateSourceMap(&source_map_); PopulateLazyBindingsMap(); } @@ -1161,8 +1164,13 @@ void Dispatcher::DidCreateScriptContext( ModuleSystem::NativesEnabledScope natives_enabled_scope( module_system); + // Register the core extensions native handlers. RegisterNativeHandlers(module_system, context); + // Register native handlers from the extensions embedder. + ExtensionsRendererClient::Get()->RegisterNativeHandlers(module_system, + context); + module_system->RegisterNativeHandler("chrome", scoped_ptr<NativeHandler>(new ChromeNativeHandler(context))); module_system->RegisterNativeHandler("print", diff --git a/chrome/renderer/extensions/renderer_permissions_policy_delegate_unittest.cc b/chrome/renderer/extensions/renderer_permissions_policy_delegate_unittest.cc index ff80d40..4cd5d97 100644 --- a/chrome/renderer/extensions/renderer_permissions_policy_delegate_unittest.cc +++ b/chrome/renderer/extensions/renderer_permissions_policy_delegate_unittest.cc @@ -13,6 +13,7 @@ #include "extensions/common/extension_builder.h" #include "extensions/common/extension_messages.h" #include "extensions/common/permissions/permissions_data.h" +#include "extensions/renderer/test_extensions_renderer_client.h" #include "testing/gtest/include/gtest/gtest.h" namespace extensions { @@ -23,17 +24,22 @@ class RendererPermissionsPolicyDelegateTest : public testing::Test { public: RendererPermissionsPolicyDelegateTest() { } - virtual void SetUp() { + + virtual void SetUp() OVERRIDE { testing::Test::SetUp(); render_thread_.reset(new content::MockRenderThread()); + renderer_client_.reset(new TestExtensionsRendererClient); + ExtensionsRendererClient::Set(renderer_client_.get()); extension_dispatcher_.reset(new Dispatcher()); policy_delegate_.reset( new RendererPermissionsPolicyDelegate(extension_dispatcher_.get())); } + protected: + scoped_ptr<content::MockRenderThread> render_thread_; + scoped_ptr<ExtensionsRendererClient> renderer_client_; scoped_ptr<Dispatcher> extension_dispatcher_; scoped_ptr<RendererPermissionsPolicyDelegate> policy_delegate_; - scoped_ptr<content::MockRenderThread> render_thread_; }; scoped_refptr<const Extension> CreateTestExtension(const std::string& id) { diff --git a/chrome/test/base/chrome_render_view_test.cc b/chrome/test/base/chrome_render_view_test.cc index 732e2f1..a1ddd2f 100644 --- a/chrome/test/base/chrome_render_view_test.cc +++ b/chrome/test/base/chrome_render_view_test.cc @@ -41,7 +41,11 @@ using autofill::AutofillAgent; using autofill::PasswordAutofillAgent; using autofill::PasswordGenerationAgent; -ChromeRenderViewTest::ChromeRenderViewTest() : extension_dispatcher_(NULL) { +ChromeRenderViewTest::ChromeRenderViewTest() + : password_autofill_(NULL), + password_generation_(NULL), + autofill_agent_(NULL), + chrome_render_thread_(NULL) { } ChromeRenderViewTest::~ChromeRenderViewTest() { @@ -54,8 +58,6 @@ void ChromeRenderViewTest::SetUp() { chrome_render_thread_ = new ChromeMockRenderThread(); render_thread_.reset(chrome_render_thread_); - extension_dispatcher_ = new extensions::Dispatcher(); - content::RenderViewTest::SetUp(); // RenderView doesn't expose its Agent objects, because it has no need to @@ -68,8 +70,9 @@ void ChromeRenderViewTest::SetUp() { } void ChromeRenderViewTest::TearDown() { - extension_dispatcher_->OnRenderProcessShutdown(); - extension_dispatcher_ = NULL; + ChromeContentRendererClient* client = + static_cast<ChromeContentRendererClient*>(content_renderer_client_.get()); + client->GetExtensionDispatcherForTest()->OnRenderProcessShutdown(); #if defined(LEAK_SANITIZER) // Do this before shutting down V8 in RenderViewTest::TearDown(). @@ -91,7 +94,7 @@ content::ContentBrowserClient* content::ContentRendererClient* ChromeRenderViewTest::CreateContentRendererClient() { ChromeContentRendererClient* client = new ChromeContentRendererClient(); - client->SetExtensionDispatcher(extension_dispatcher_); + client->SetExtensionDispatcherForTest(new extensions::Dispatcher); #if defined(ENABLE_SPELLCHECK) client->SetSpellcheck(new SpellCheck()); #endif diff --git a/chrome/test/base/chrome_render_view_test.h b/chrome/test/base/chrome_render_view_test.h index 69bd244..5c4824f 100644 --- a/chrome/test/base/chrome_render_view_test.h +++ b/chrome/test/base/chrome_render_view_test.h @@ -16,10 +16,6 @@ class TestPasswordAutofillAgent; class TestPasswordGenerationAgent; } -namespace extensions { -class Dispatcher; -} - class ChromeRenderViewTest : public content::RenderViewTest { public: ChromeRenderViewTest(); @@ -34,8 +30,6 @@ class ChromeRenderViewTest : public content::RenderViewTest { virtual content::ContentRendererClient* CreateContentRendererClient() OVERRIDE; - extensions::Dispatcher* extension_dispatcher_; - autofill::TestPasswordAutofillAgent* password_autofill_; autofill::TestPasswordGenerationAgent* password_generation_; autofill::AutofillAgent* autofill_agent_; diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 8d4d97e..5486d77 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -807,6 +807,7 @@ enum HistogramValue { BLUETOOTHSOCKET_GETINFO, BLUETOOTHSOCKET_GETSOCKETS, WEBSTOREPRIVATE_SIGNINFUNCTION, + SHELL_CREATEWINDOW, // Last entry: Add new entries above and ensure to update // tools/metrics/histograms/histograms/histograms.xml. ENUM_BOUNDARY diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 255a68f..133a19e 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp @@ -510,6 +510,8 @@ 'common/test_util.h', 'common/value_builder.cc', 'common/value_builder.h', + 'renderer/test_extensions_renderer_client.cc', + 'renderer/test_extensions_renderer_client.h', ], # Disable c4267 warnings until we fix size_t to int truncations. 'msvs_disabled_warnings': [ 4267, ], diff --git a/extensions/renderer/extensions_renderer_client.cc b/extensions/renderer/extensions_renderer_client.cc index 6fb5a96..91c5aeb 100644 --- a/extensions/renderer/extensions_renderer_client.cc +++ b/extensions/renderer/extensions_renderer_client.cc @@ -5,6 +5,7 @@ #include "extensions/renderer/extensions_renderer_client.h" #include "base/basictypes.h" +#include "base/logging.h" namespace extensions { @@ -14,7 +15,10 @@ ExtensionsRendererClient* g_client = NULL; } // namespace -ExtensionsRendererClient* ExtensionsRendererClient::Get() { return g_client; } +ExtensionsRendererClient* ExtensionsRendererClient::Get() { + CHECK(g_client); + return g_client; +} void ExtensionsRendererClient::Set(ExtensionsRendererClient* client) { g_client = client; diff --git a/extensions/renderer/extensions_renderer_client.h b/extensions/renderer/extensions_renderer_client.h index b8f5255..6b06b6c 100644 --- a/extensions/renderer/extensions_renderer_client.h +++ b/extensions/renderer/extensions_renderer_client.h @@ -5,8 +5,13 @@ #ifndef EXTENSIONS_RENDERER_EXTENSIONS_RENDERER_CLIENT_H_ #define EXTENSIONS_RENDERER_EXTENSIONS_RENDERER_CLIENT_H_ +class ResourceBundleSourceMap; + namespace extensions { +class ModuleSystem; +class ScriptContext; + // Interface to allow the extensions module to make render-process-specific // queries of the embedder. Should be Set() once in the render process. // @@ -25,6 +30,13 @@ class ExtensionsRendererClient { // (third_party/WebKit/public/web/WebFrame.h) for additional context. virtual int GetLowestIsolatedWorldId() const = 0; + // Registers additional native C++ code handlers for JS API functions. + virtual void RegisterNativeHandlers(ModuleSystem* module_system, + ScriptContext* context) = 0; + + // Registers additional JS source code resources for API implementations. + virtual void PopulateSourceMap(ResourceBundleSourceMap* source_map) = 0; + // Returns the single instance of |this|. static ExtensionsRendererClient* Get(); diff --git a/extensions/renderer/test_extensions_renderer_client.cc b/extensions/renderer/test_extensions_renderer_client.cc new file mode 100644 index 0000000..4d1c021 --- /dev/null +++ b/extensions/renderer/test_extensions_renderer_client.cc @@ -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. + +#include "extensions/renderer/test_extensions_renderer_client.h" + +namespace extensions { + +TestExtensionsRendererClient::TestExtensionsRendererClient() {} + +TestExtensionsRendererClient::~TestExtensionsRendererClient() {} + +bool TestExtensionsRendererClient::IsIncognitoProcess() const { + return false; +} + +int TestExtensionsRendererClient::GetLowestIsolatedWorldId() const { + // Note that 0 is reserved for the global world. + return 1; +} + +void TestExtensionsRendererClient::RegisterNativeHandlers( + extensions::ModuleSystem* module_system, + extensions::ScriptContext* context) { +} + +void TestExtensionsRendererClient::PopulateSourceMap( + ResourceBundleSourceMap* source_map) { +} + +} // namespace extensions diff --git a/extensions/renderer/test_extensions_renderer_client.h b/extensions/renderer/test_extensions_renderer_client.h new file mode 100644 index 0000000..a71d1bb --- /dev/null +++ b/extensions/renderer/test_extensions_renderer_client.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 EXTENSIONS_RENDERER_TEST_EXTENSIONS_RENDERER_CLIENT_H_ +#define EXTENSIONS_RENDERER_TEST_EXTENSIONS_RENDERER_CLIENT_H_ + +#include "base/macros.h" +#include "extensions/renderer/extensions_renderer_client.h" + +namespace extensions { + +class TestExtensionsRendererClient : public ExtensionsRendererClient { + public: + TestExtensionsRendererClient(); + virtual ~TestExtensionsRendererClient(); + + // ExtensionsRendererClient implementation. + virtual bool IsIncognitoProcess() const OVERRIDE; + virtual int GetLowestIsolatedWorldId() const OVERRIDE; + virtual void RegisterNativeHandlers(ModuleSystem* module_system, + ScriptContext* context) OVERRIDE; + virtual void PopulateSourceMap(ResourceBundleSourceMap* source_map) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(TestExtensionsRendererClient); +}; + +} // namespace extensions + +#endif // EXTENSIONS_RENDERER_TEST_EXTENSIONS_RENDERER_CLIENT_H_ diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index 819b135..4ecaabd 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids @@ -171,6 +171,9 @@ "extensions/extensions_strings.grd": { "messages": [27000], }, + "apps/shell/app_shell_resources.grd": { + "includes": [27400], + }, "chrome/browser/resources/memory_internals_resources.grd": { "includes": [27500], }, diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 1688a7f..1d99d3f 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -33736,6 +33736,7 @@ Therefore, the affected-histogram name has to have at least one dot in it. <int value="746" label="BLUETOOTHSOCKET_GETINFO"/> <int value="747" label="BLUETOOTHSOCKET_GETSOCKETS"/> <int value="748" label="WEBSTOREPRIVATE_SIGNINFUNCTION"/> + <int value="749" label="SHELL_CREATEWINDOW"/> </enum> <enum name="ExtensionInstallCause" type="int"> |