Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: headless/lib/renderer/headless_content_renderer_client.cc

Issue 2049363003: Adds support for headless chrome embedder mojo services (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactored the JS for clarity Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "headless/lib/renderer/headless_content_renderer_client.h" 5 #include "headless/lib/renderer/headless_content_renderer_client.h"
6 6
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/public/renderer/render_frame.h"
9
7 namespace headless { 10 namespace headless {
8 11
9 HeadlessContentRendererClient::HeadlessContentRendererClient() {} 12 HeadlessContentRendererClient::HeadlessContentRendererClient() {}
10 13
11 HeadlessContentRendererClient::~HeadlessContentRendererClient() {} 14 HeadlessContentRendererClient::~HeadlessContentRendererClient() {}
12 15
16 void HeadlessContentRendererClient::RunScriptsAtDocumentStart(
17 content::RenderFrame* render_frame) {
18 render_frame->ExecuteJavaScript(base::UTF8ToUTF16(R"(
19 // Shim to let code use define() instead of mojo.define()
20 window.define = (function() {
21 let moduleCache = new Map();
22 return function(name, deps, factory) {
23 let promise = moduleCache.get(name);
24 if (promise === undefined) {
25 // This promise must be cached as mojo.define will only call the
26 // factory function the first time the module is defined.
27 promise = new Promise(resolve => {
28 mojo.define(name, deps, (...modules) => {
29 let result = factory(...modules);
30 resolve(result);
31 return result;
Sami 2016/06/20 16:58:16 Did you mention this return could be removed?
alex clarke (OOO till 29th) 2016/06/20 23:19:13 We need the return but the resolve isn't needed.
32 });
33 });
34 moduleCache.set(name, promise);
35 }
36 return promise;
37 }
38 })();
39
40 // This code is run before the browser has sent us the mojo bindings so
41 // we need to get fancy and use nested proxy classes to define a promise
42 // to an arbitary window.mojo.services.myModule.myInterface.
43 if (window.hasOwnProperty("mojo")) {
44 let mojoBindings = new Map();
45 let resolvePending = true;
46
47 // Factory for returning the second level dynamic property which
48 // resolves to a promise to the corresponding mojo inteerface..
Sami 2016/06/20 16:58:16 typo: interface.
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Done.
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Done.
49 let interfaceProxyFactory = function(serviceName) {
50 return new Proxy({}, {
51 get: function(target, interfaceName) {
52 let name = serviceName + "::" + interfaceName;
53 let binding = mojoBindings.get(name);
54 if (binding === undefined) {
55 binding = {};
56 binding.promise = new Promise(function(resolve, reject) {
57 binding.resolve = resolve;
58 binding.reject = reject;
59 if (!resolvePending)
60 reject();
61 });
62 mojoBindings.set(name, binding);
63 }
64 return binding.promise;
65 },
66 set: function(target, name, value) {
67 return false;
Sami 2016/06/20 16:58:16 Should we throw an Error here?
alex clarke (OOO till 29th) 2016/06/21 09:16:45 Done.
68 }
69 });
70 };
71
72 // Top level dynamic property.
73 window.mojo.services = new Proxy({}, {
74 get: function(target, serviceName) {
75 if (!(serviceName in target)) {
76 let interfaceProxy = interfaceProxyFactory(serviceName);
77 target[serviceName] = interfaceProxy;
78 return interfaceProxy;
79 }
80 return target[serviceName];
81 },
82 set: function(target, name, value) {
83 return false;
Sami 2016/06/20 16:58:16 Ditto.
alex clarke (OOO till 29th) 2016/06/21 09:16:45 Done.
84 }
85 });
86
87 // Resolve promises for the listed |serviceNames|.
88 window.mojo.resolvePromisesForServices = function(serviceNames) {
Sami 2016/06/20 16:58:16 Should we call this resolvePromisesForServices_ si
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Done.
89 let numServices = serviceNames.length;
90 for (let i = 0; i < numServices; ++i) {
91 let serviceName = serviceNames[i];
92 // Use mojo to obtain the module binding.
93 define([
94 serviceName,
95 "mojo/public/js/core",
96 "mojo/public/js/router",
97 "content/public/renderer/frame_service_registry",
98 ], function(serviceMojom, mojoCore, routerModule,
99 serviceProvider) {
100 // A mojom binding may contain bindings for a number of
101 // interfaces. Iterate through all of them and resolve any
102 // promises.
103 for (var m in serviceMojom) {
Sami 2016/06/20 16:58:16 s/var/let/ Also maybe "for..of" would be more app
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Done.
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Done.
Sami 2016/06/21 10:22:26 (Did you mean to leave the "in" here? Sometimes it
alex clarke (OOO till 29th) 2016/06/21 10:38:37 for..of only works for iterables but serviceMojom
104 if (typeof serviceMojom[m] == "object") {
105 let service = serviceMojom[m];
106 let binding = mojoBindings.get(service.name);
107 let interface = new service.proxyClass(
108 new routerModule.Router(
109 serviceProvider.connectToService(service.name)));
110 if (binding === undefined) {
111 // Store resolved promise in case binding is requested.
112 mojoBindings.set(
113 service.name, {"promise": Promise.resolve(interface)});
114 } else {
115 binding.resolve(interface);
116 // Since this promise has been resolved we don't want to try
117 // and reject it below!
118 delete binding.reject;
119 }
120 }
121 }
122 });
123 }
124 // Reject any remaining promises that didn't get resolved.
125 for (let [key, value] of mojoBindings) {
126 if ("reject" in value) {
127 value.reject();
128 }
129 }
130 // Reject any subsequent unknown properties.
131 resolvePending = false;
132 };
133 } )"));
134 }
135
13 } // namespace headless 136 } // namespace headless
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698