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

Side by Side Diff: ios/web/webui/crw_web_ui_manager.mm

Issue 2946383002: Support new-style Mojo JS core API on IOS. (Closed)
Patch Set: . Created 3 years, 5 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
« no previous file with comments | « ios/web/test/data/mojo_test.js ('k') | ios/web/webui/crw_web_ui_manager_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #import "ios/web/webui/crw_web_ui_manager.h" 5 #import "ios/web/webui/crw_web_ui_manager.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/json/string_escape.h" 10 #include "base/json/string_escape.h"
11 #import "base/mac/bind_objc_block.h" 11 #import "base/mac/bind_objc_block.h"
12 #import "base/mac/scoped_nsobject.h" 12 #import "base/mac/scoped_nsobject.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/memory/ref_counted_memory.h" 14 #include "base/memory/ref_counted_memory.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #import "base/strings/sys_string_conversions.h" 16 #import "base/strings/sys_string_conversions.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "base/values.h" 18 #include "base/values.h"
19 #include "ios/web/grit/ios_web_resources.h" 19 #include "ios/web/grit/ios_web_resources.h"
20 #include "ios/web/public/browser_state.h" 20 #include "ios/web/public/browser_state.h"
21 #import "ios/web/public/web_client.h" 21 #import "ios/web/public/web_client.h"
22 #import "ios/web/public/web_state/navigation_context.h" 22 #import "ios/web/public/web_state/navigation_context.h"
23 #import "ios/web/public/web_state/web_state_observer_bridge.h" 23 #import "ios/web/public/web_state/web_state_observer_bridge.h"
24 #import "ios/web/web_state/web_state_impl.h" 24 #import "ios/web/web_state/web_state_impl.h"
25 #import "ios/web/webui/crw_web_ui_page_builder.h" 25 #import "ios/web/webui/crw_web_ui_page_builder.h"
26 #include "ios/web/webui/mojo_js_constants.h"
27 #import "ios/web/webui/url_fetcher_block_adapter.h" 26 #import "ios/web/webui/url_fetcher_block_adapter.h"
28 #include "mojo/public/js/constants.h"
29 #import "net/base/mac/url_conversions.h" 27 #import "net/base/mac/url_conversions.h"
30 28
31 #if !defined(__has_feature) || !__has_feature(objc_arc) 29 #if !defined(__has_feature) || !__has_feature(objc_arc)
32 #error "This file requires ARC support." 30 #error "This file requires ARC support."
33 #endif 31 #endif
34 32
35 namespace { 33 namespace {
36 // Prefix for JavaScript messages. 34 // Prefix for JavaScript messages.
37 const char kScriptCommandPrefix[] = "webui"; 35 const char kScriptCommandPrefix[] = "webui";
38 } 36 }
39 37
40 @interface CRWWebUIManager () <CRWWebUIPageBuilderDelegate> 38 @interface CRWWebUIManager () <CRWWebUIPageBuilderDelegate>
41 39
42 // Current web state. 40 // Current web state.
43 @property(nonatomic, readonly) web::WebStateImpl* webState; 41 @property(nonatomic, readonly) web::WebStateImpl* webState;
44 42
45 // Composes WebUI page for webUIURL and invokes completionHandler with the 43 // Composes WebUI page for webUIURL and invokes completionHandler with the
46 // result. 44 // result.
47 - (void)loadWebUIPageForURL:(const GURL&)webUIURL 45 - (void)loadWebUIPageForURL:(const GURL&)webUIURL
48 completionHandler:(void (^)(NSString*))completionHandler; 46 completionHandler:(void (^)(NSString*))completionHandler;
49 47
50 // Retrieves resource for URL and invokes completionHandler with the result. 48 // Retrieves resource for URL and invokes completionHandler with the result.
51 - (void)fetchResourceWithURL:(const GURL&)URL 49 - (void)fetchResourceWithURL:(const GURL&)URL
52 completionHandler:(void (^)(NSData*))completionHandler; 50 completionHandler:(void (^)(NSData*))completionHandler;
53 51
54 // Handles JavaScript message from the WebUI page. 52 // Handles JavaScript message from the WebUI page.
55 - (BOOL)handleWebUIJSMessage:(const base::DictionaryValue&)message; 53 - (BOOL)handleWebUIJSMessage:(const base::DictionaryValue&)message;
56 54
57 // Handles webui.loadMojo JavaScript message from the WebUI page.
58 - (BOOL)handleLoadMojo:(const base::ListValue*)arguments;
59
60 // Executes mojo script and signals |webui.loadMojo| finish.
61 - (void)executeMojoScript:(const std::string&)mojoScript
62 forModuleName:(const std::string&)moduleName
63 loadID:(const std::string&)loadID;
64
65 // Removes favicon callback from web state. 55 // Removes favicon callback from web state.
66 - (void)resetWebState; 56 - (void)resetWebState;
67 57
68 // Removes fetcher from vector of active fetchers. 58 // Removes fetcher from vector of active fetchers.
69 - (void)removeFetcher:(web::URLFetcherBlockAdapter*)fetcher; 59 - (void)removeFetcher:(web::URLFetcherBlockAdapter*)fetcher;
70 60
71 @end 61 @end
72 62
73 @implementation CRWWebUIManager { 63 @implementation CRWWebUIManager {
74 // Set of live WebUI fetchers for retrieving data. 64 // Set of live WebUI fetchers for retrieving data.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 if (!message.GetList("arguments", &arguments)) { 171 if (!message.GetList("arguments", &arguments)) {
182 DLOG(WARNING) << "JS message parameter not found: arguments"; 172 DLOG(WARNING) << "JS message parameter not found: arguments";
183 return NO; 173 return NO;
184 } 174 }
185 175
186 if (!arguments) { 176 if (!arguments) {
187 DLOG(WARNING) << "No arguments provided to " << command; 177 DLOG(WARNING) << "No arguments provided to " << command;
188 return NO; 178 return NO;
189 } 179 }
190 180
191 if (command == "webui.loadMojo")
192 return [self handleLoadMojo:arguments];
193
194 DLOG(WARNING) << "Unknown webui command received: " << command; 181 DLOG(WARNING) << "Unknown webui command received: " << command;
195 return NO; 182 return NO;
196 } 183 }
197 184
198 - (BOOL)handleLoadMojo:(const base::ListValue*)arguments {
199 std::string moduleName;
200 if (!arguments->GetString(0, &moduleName)) {
201 DLOG(WARNING) << "JS message parameter not found: Module name";
202 return NO;
203 }
204 std::string loadID;
205 if (!arguments->GetString(1, &loadID)) {
206 DLOG(WARNING) << "JS message parameter not found: Load ID";
207 return NO;
208 }
209
210 // Look for built-in scripts first.
211 std::map<std::string, int> resource_map{
212 {mojo::kAssociatedBindingsModuleName, IDR_MOJO_ASSOCIATED_BINDINGS_JS},
213 {mojo::kBindingsModuleName, IDR_MOJO_BINDINGS_JS},
214 {mojo::kBufferModuleName, IDR_MOJO_BUFFER_JS},
215 {mojo::kCodecModuleName, IDR_MOJO_CODEC_JS},
216 {mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS},
217 {mojo::kControlMessageHandlerModuleName,
218 IDR_MOJO_CONTROL_MESSAGE_HANDLER_JS},
219 {mojo::kControlMessageProxyModuleName, IDR_MOJO_CONTROL_MESSAGE_PROXY_JS},
220 {mojo::kInterfaceControlMessagesMojom,
221 IDR_MOJO_INTERFACE_CONTROL_MESSAGES_MOJOM_JS},
222 {mojo::kInterfaceTypesModuleName, IDR_MOJO_INTERFACE_TYPES_JS},
223 {mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS},
224 {mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS},
225 {mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS},
226 {web::kConsoleModuleName, IDR_IOS_CONSOLE_JS},
227 {web::kTimerModuleName, IDR_IOS_TIMER_JS},
228 {web::kCoreModuleName, IDR_IOS_MOJO_CORE_JS},
229 {web::kHandleUtilModuleName, IDR_IOS_MOJO_HANDLE_UTIL_JS},
230 {web::kInterfaceProviderModuleName, IDR_IOS_SHELL_INTERFACE_PROVIDER_JS},
231 {web::kSupportModuleName, IDR_IOS_MOJO_SUPPORT_JS},
232 {web::kSyncMessageChannelModuleName,
233 IDR_IOS_MOJO_SYNC_MESSAGE_CHANNEL_JS},
234 {mojo::kPipeControlMessagesMojom,
235 IDR_MOJO_PIPE_CONTROL_MESSAGES_MOJOM_JS},
236 {mojo::kInterfaceEndpointClientModuleName,
237 IDR_MOJO_INTERFACE_ENDPOINT_CLIENT_JS},
238 {mojo::kInterfaceEndpointHandleModuleName,
239 IDR_MOJO_INTERFACE_ENDPOINT_HANDLE_JS},
240 {mojo::kPipeControlMessageHandlerModuleName,
241 IDR_MOJO_PIPE_CONTROL_MESSAGE_HANDLER_JS},
242 {mojo::kPipeControlMessageProxyModuleName,
243 IDR_MOJO_PIPE_CONTROL_MESSAGE_PROXY_JS},
244 };
245 scoped_refptr<base::RefCountedMemory> scriptData(
246 web::GetWebClient()->GetDataResourceBytes(resource_map[moduleName]));
247 if (scriptData) {
248 std::string script(reinterpret_cast<const char*>(scriptData->front()),
249 scriptData->size());
250 [self executeMojoScript:script forModuleName:moduleName loadID:loadID];
251 return YES;
252 }
253
254 // Not a built-in script, try retrieving from network.
255 GURL resourceURL(self.webState->GetLastCommittedURL().Resolve(moduleName));
256 base::WeakNSObject<CRWWebUIManager> weakSelf(self);
257 [self fetchResourceWithURL:resourceURL completionHandler:^(NSData* data) {
258 std::string script;
259 if (data) {
260 script = base::SysNSStringToUTF8(
261 [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
262 // WebUIIOSDataSourceImpl returns the default resource (which is the HTML
263 // page itself) if the resource URL isn't found. Fail with error instead
264 // of silently injecting garbage (leading to a not-very-useful syntax
265 // error from the JS side).
266 if (script.find("<!doctype") != std::string::npos) {
267 NOTREACHED() << "cannot load " << moduleName;
268 script.clear();
269 }
270 }
271
272 [weakSelf executeMojoScript:script forModuleName:moduleName loadID:loadID];
273 }];
274
275 return YES;
276 }
277
278 - (void)executeMojoScript:(const std::string&)mojoScript
279 forModuleName:(const std::string&)moduleName
280 loadID:(const std::string&)loadID {
281 std::string script = mojoScript;
282 // Append with completion function call.
283 if (script.empty()) {
284 DLOG(ERROR) << "Unable to find a module named " << moduleName;
285 script = "__crWeb.webUIModuleLoadNotifier.moduleLoadFailed";
286 } else {
287 script += "__crWeb.webUIModuleLoadNotifier.moduleLoadCompleted";
288 }
289 base::StringAppendF(&script, "(%s, %s);",
290 base::GetQuotedJSONString(moduleName).c_str(),
291 base::GetQuotedJSONString(loadID).c_str());
292
293 _webState->ExecuteJavaScript(base::UTF8ToUTF16(script));
294 }
295
296 - (void)resetWebState { 185 - (void)resetWebState {
297 if (_webState) { 186 if (_webState) {
298 _webState->RemoveScriptCommandCallback(kScriptCommandPrefix); 187 _webState->RemoveScriptCommandCallback(kScriptCommandPrefix);
299 } 188 }
300 _webState = nullptr; 189 _webState = nullptr;
301 } 190 }
302 191
303 - (web::WebStateImpl*)webState { 192 - (web::WebStateImpl*)webState {
304 return _webState; 193 return _webState;
305 } 194 }
306 195
307 - (void)removeFetcher:(web::URLFetcherBlockAdapter*)fetcher { 196 - (void)removeFetcher:(web::URLFetcherBlockAdapter*)fetcher {
308 _fetchers.erase(std::find_if( 197 _fetchers.erase(std::find_if(
309 _fetchers.begin(), _fetchers.end(), 198 _fetchers.begin(), _fetchers.end(),
310 [fetcher](const std::unique_ptr<web::URLFetcherBlockAdapter>& ptr) { 199 [fetcher](const std::unique_ptr<web::URLFetcherBlockAdapter>& ptr) {
311 return ptr.get() == fetcher; 200 return ptr.get() == fetcher;
312 })); 201 }));
313 } 202 }
314 203
315 #pragma mark - Testing-Only Methods 204 #pragma mark - Testing-Only Methods
316 205
317 - (std::unique_ptr<web::URLFetcherBlockAdapter>) 206 - (std::unique_ptr<web::URLFetcherBlockAdapter>)
318 fetcherForURL:(const GURL&)URL 207 fetcherForURL:(const GURL&)URL
319 completionHandler:(web::URLFetcherBlockAdapterCompletion)handler { 208 completionHandler:(web::URLFetcherBlockAdapterCompletion)handler {
320 return base::MakeUnique<web::URLFetcherBlockAdapter>( 209 return base::MakeUnique<web::URLFetcherBlockAdapter>(
321 URL, _webState->GetBrowserState()->GetRequestContext(), handler); 210 URL, _webState->GetBrowserState()->GetRequestContext(), handler);
322 } 211 }
323 212
324 @end 213 @end
OLDNEW
« no previous file with comments | « ios/web/test/data/mojo_test.js ('k') | ios/web/webui/crw_web_ui_manager_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698