summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/shell/DEPS12
-rw-r--r--apps/shell/app_shell.gyp23
-rw-r--r--apps/shell/app_shell_resources.grd15
-rw-r--r--apps/shell/browser/api/shell/shell_api.cc62
-rw-r--r--apps/shell/browser/api/shell/shell_api.h33
-rw-r--r--apps/shell/browser/shell_extensions_browser_client.cc4
-rw-r--r--apps/shell/common/api/api.gyp36
-rw-r--r--apps/shell/common/api/shell.idl50
-rw-r--r--apps/shell/common/shell_extensions_client.cc7
-rw-r--r--apps/shell/renderer/DEPS3
-rw-r--r--apps/shell/renderer/shell_content_renderer_client.cc13
-rw-r--r--apps/shell/renderer/shell_custom_bindings.cc57
-rw-r--r--apps/shell/renderer/shell_custom_bindings.h25
-rw-r--r--apps/shell/renderer/shell_custom_bindings.js78
-rw-r--r--apps/shell/renderer/shell_extensions_renderer_client.cc19
-rw-r--r--apps/shell/renderer/shell_extensions_renderer_client.h4
-rw-r--r--chrome/common/extensions/api/_api_features.json6
-rw-r--r--chrome/common/extensions/docs/examples/apps/calculator/app/controller.js6
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc20
-rw-r--r--chrome/renderer/chrome_content_renderer_client.h6
-rw-r--r--chrome/renderer/extensions/chrome_extensions_renderer_client.cc9
-rw-r--r--chrome/renderer/extensions/chrome_extensions_renderer_client.h4
-rw-r--r--chrome/renderer/extensions/dispatcher.cc8
-rw-r--r--chrome/renderer/extensions/renderer_permissions_policy_delegate_unittest.cc10
-rw-r--r--chrome/test/base/chrome_render_view_test.cc15
-rw-r--r--chrome/test/base/chrome_render_view_test.h6
-rw-r--r--extensions/browser/extension_function_histogram_value.h1
-rw-r--r--extensions/extensions.gyp2
-rw-r--r--extensions/renderer/extensions_renderer_client.cc6
-rw-r--r--extensions/renderer/extensions_renderer_client.h12
-rw-r--r--extensions/renderer/test_extensions_renderer_client.cc31
-rw-r--r--extensions/renderer/test_extensions_renderer_client.h31
-rw-r--r--tools/gritsettings/resource_ids3
-rw-r--r--tools/metrics/histograms/histograms.xml1
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">