Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #import "ios/web/webui/crw_web_ui_manager.h" | |
| 6 | |
| 7 #include "base/mac/bind_objc_block.h" | |
| 8 #include "base/mac/scoped_nsobject.h" | |
| 9 #include "base/memory/scoped_vector.h" | |
| 10 #import "base/strings/sys_string_conversions.h" | |
| 11 #include "base/values.h" | |
| 12 #import "ios/web/net/request_group_util.h" | |
| 13 #include "ios/web/public/browser_state.h" | |
| 14 #import "ios/web/public/web_state/web_state_observer_bridge.h" | |
| 15 #include "ios/web/public/web_client.h" | |
| 16 #include "ios/web/web_state/web_state_impl.h" | |
| 17 #import "ios/web/webui/crw_web_ui_page_builder.h" | |
| 18 #include "ios/web/webui/url_fetcher_block_adapter.h" | |
| 19 #import "net/base/mac/url_conversions.h" | |
| 20 | |
| 21 namespace { | |
| 22 // Prefix for history.requestFavicon JavaScript message. | |
| 23 const char kScriptCommandPrefix[] = "webui"; | |
| 24 } | |
| 25 | |
| 26 @interface CRWWebUIManager () <CRWWebUIPageBuilderDelegate> | |
| 27 | |
| 28 // Current web state. | |
| 29 @property(nonatomic, readonly) web::WebStateImpl* webState; | |
| 30 | |
| 31 // Composes WebUI page for webUIURL and invokes completionHandler with the | |
| 32 // result. | |
| 33 - (void)loadWebUIPageForURL:(const GURL&)webUIURL | |
| 34 completionHandler:(void (^)(NSString*))completionHandler; | |
| 35 | |
| 36 // Retrieves resource for URL and invokes completionHandler with the result. | |
| 37 - (void)fetchResourceWithURL:(const GURL&)URL | |
| 38 completionHandler:(void (^)(NSData*))completionHandler; | |
| 39 | |
| 40 // Handles JavaScript message from the WebUI page. | |
|
Eugene But (OOO till 7-30)
2015/05/12 17:47:09
Please expand the comments, describing what this m
Jackie Quinn
2015/05/12 18:14:54
I was asked by Stuart to make the method name and
| |
| 41 - (BOOL)handleWebUIJSMessage:(const base::DictionaryValue&)message; | |
| 42 | |
| 43 // Removes favicon callback from web state. | |
| 44 - (void)resetWebState; | |
| 45 | |
| 46 // Removes fetcher from vector of active fetchers. | |
| 47 - (void)removeFetcher:(web::URLFetcherBlockAdapter*)fetcher; | |
| 48 | |
| 49 @end | |
| 50 | |
| 51 @implementation CRWWebUIManager { | |
| 52 // Set of live WebUI fetchers for retrieving data. | |
| 53 ScopedVector<web::URLFetcherBlockAdapter> _fetchers; | |
| 54 // Bridge to observe the web state from Objective-C. | |
| 55 scoped_ptr<web::WebStateObserverBridge> _webStateObserverBridge; | |
| 56 // Weak WebStateImpl this CRWWebUIManager is associated with. | |
| 57 web::WebStateImpl* _webState; | |
| 58 } | |
| 59 | |
| 60 - (instancetype)init { | |
| 61 NOTREACHED(); | |
| 62 return self; | |
| 63 } | |
| 64 | |
| 65 - (instancetype)initWithWebState:(web::WebStateImpl*)webState { | |
| 66 if (self = [super init]) { | |
| 67 _webState = webState; | |
| 68 _webStateObserverBridge.reset( | |
| 69 new web::WebStateObserverBridge(webState, self)); | |
| 70 base::WeakNSObject<CRWWebUIManager> weakSelf(self); | |
| 71 _webState->AddScriptCommandCallback( | |
| 72 base::BindBlock( | |
| 73 ^bool(const base::DictionaryValue& message, const GURL&, bool) { | |
| 74 return [weakSelf handleWebUIJSMessage:message]; | |
| 75 }), | |
| 76 kScriptCommandPrefix); | |
| 77 } | |
| 78 return self; | |
| 79 } | |
| 80 | |
| 81 - (void)dealloc { | |
| 82 [self resetWebState]; | |
| 83 [super dealloc]; | |
| 84 } | |
| 85 | |
| 86 #pragma mark - CRWWebStateObserver Methods | |
| 87 | |
| 88 - (void)webState:(web::WebState*)webState | |
| 89 didStartProvisionalNavigationForURL:(const GURL&)URL { | |
| 90 DCHECK(webState == _webState); | |
| 91 GURL navigationURL(URL); | |
| 92 // Add request group ID to the URL, if not present. Request group ID may | |
| 93 // already be added if restoring state to a WebUI page. | |
| 94 GURL requestURL = | |
| 95 web::ExtractRequestGroupIDFromURL(net::NSURLWithGURL(URL)) | |
| 96 ? URL | |
| 97 : net::GURLWithNSURL(web::AddRequestGroupIDToURL( | |
| 98 net::NSURLWithGURL(URL), _webState->GetRequestGroupID())); | |
| 99 base::WeakNSObject<CRWWebUIManager> weakSelf(self); | |
| 100 [self loadWebUIPageForURL:requestURL | |
| 101 completionHandler:^(NSString* HTML) { | |
| 102 if ([weakSelf webState]) { | |
|
Eugene But (OOO till 7-30)
2015/05/12 17:47:09
Compiler may show a warning for this code, because
Jackie Quinn
2015/05/12 18:14:55
Done.
| |
| 103 [weakSelf webState]->LoadWebUIHtml(base::SysNSStringToUTF16(HTML), | |
| 104 navigationURL); | |
| 105 } | |
| 106 }]; | |
| 107 } | |
| 108 | |
| 109 - (void)webStateDestroyed:(web::WebState*)webState { | |
| 110 [self resetWebState]; | |
| 111 } | |
| 112 | |
| 113 #pragma mark - CRWWebUIPageBuilderDelegate Methods | |
| 114 | |
| 115 - (void)webUIPageBuilder:(CRWWebUIPageBuilder*)webUIPage | |
|
Eugene But (OOO till 7-30)
2015/05/12 17:47:09
NIT: s/webUIPage/webUIPageBuilder
Jackie Quinn
2015/05/12 18:14:55
Done.
| |
| 116 fetchResourceWithURL:(const GURL&)resourceURL | |
| 117 completionHandler:(web::WebUIDelegateCompletion)completionHandler { | |
| 118 GURL URL(resourceURL); | |
| 119 [self fetchResourceWithURL:URL | |
| 120 completionHandler:^(NSData* data) { | |
| 121 base::scoped_nsobject<NSString> resource( | |
| 122 [[NSString alloc] initWithData:data | |
| 123 encoding:NSUTF8StringEncoding]); | |
| 124 completionHandler(resource, URL); | |
| 125 }]; | |
| 126 } | |
| 127 | |
| 128 #pragma mark - Private Methods | |
| 129 | |
| 130 - (void)loadWebUIPageForURL:(const GURL&)webUIURL | |
| 131 completionHandler:(void (^)(NSString*))handler { | |
| 132 base::scoped_nsobject<CRWWebUIPageBuilder> pageBuilder( | |
| 133 [[CRWWebUIPageBuilder alloc] initWithDelegate:self]); | |
| 134 [pageBuilder buildWebUIPageForURL:webUIURL completionHandler:handler]; | |
| 135 } | |
| 136 | |
| 137 - (void)fetchResourceWithURL:(const GURL&)URL | |
| 138 completionHandler:(void (^)(NSData*))completionHandler { | |
| 139 base::WeakNSObject<CRWWebUIManager> weakSelf(self); | |
| 140 web::URLFetcherBlockAdapterCompletion fetcherCompletion = | |
| 141 ^(NSData* data, web::URLFetcherBlockAdapter* fetcher) { | |
| 142 completionHandler(data); | |
| 143 [weakSelf removeFetcher:fetcher]; | |
| 144 }; | |
| 145 | |
| 146 _fetchers.push_back( | |
| 147 [self fetcherForURL:URL completionHandler:fetcherCompletion].Pass()); | |
| 148 _fetchers.back()->Start(); | |
| 149 } | |
| 150 | |
| 151 - (BOOL)handleWebUIJSMessage:(const base::DictionaryValue&)message { | |
| 152 const std::string command; | |
| 153 if (!message.GetString("message", &command) || !message == "requestFavicon") { | |
| 154 DLOG(WARNING) << "Unexpected message received" << command; | |
| 155 return NO; | |
| 156 } | |
| 157 const base::ListValue* arguments = nullptr; | |
| 158 if (!message.GetList("arguments", &arguments)) { | |
| 159 DLOG(WARNING) << "JS message parameter not found: arguments"; | |
| 160 return NO; | |
| 161 } | |
| 162 std::string favicon; | |
| 163 if (!arguments->GetString(0, &favicon)) { | |
| 164 DLOG(WARNING) << "JS message parameter not found: Favicon URL"; | |
| 165 return NO; | |
| 166 } | |
| 167 GURL faviconURL(favicon); | |
| 168 DCHECK(faviconURL.is_valid()); | |
| 169 // Retrieve favicon resource and set favicon background image via JavaScript. | |
| 170 base::WeakNSObject<CRWWebUIManager> weakSelf(self); | |
| 171 void (^faviconHandler)(NSData*) = ^void(NSData* data) { | |
| 172 NSString* base64EncodedResource = [data base64EncodedStringWithOptions:0]; | |
| 173 NSString* dataURLString = [NSString | |
| 174 stringWithFormat:@"data:image/png;base64,%@", base64EncodedResource]; | |
| 175 NSString* faviconURLString = base::SysUTF8ToNSString(faviconURL.spec()); | |
| 176 NSString* script = | |
| 177 [NSString stringWithFormat:@"chrome.setFaviconBackground('%@', '%@');", | |
| 178 faviconURLString, dataURLString]; | |
| 179 [weakSelf webState]->ExecuteJavaScriptAsync( | |
| 180 base::SysNSStringToUTF16(script)); | |
| 181 }; | |
| 182 [self fetchResourceWithURL:faviconURL completionHandler:faviconHandler]; | |
| 183 return YES; | |
| 184 } | |
| 185 | |
| 186 - (void)resetWebState { | |
| 187 if (_webState) { | |
| 188 _webState->RemoveScriptCommandCallback(kScriptCommandPrefix); | |
| 189 } | |
| 190 _webState = nullptr; | |
| 191 } | |
| 192 | |
| 193 - (web::WebStateImpl*)webState { | |
| 194 return _webState; | |
| 195 } | |
| 196 | |
| 197 - (void)removeFetcher:(web::URLFetcherBlockAdapter*)fetcher { | |
| 198 _fetchers.erase(std::find(_fetchers.begin(), _fetchers.end(), fetcher)); | |
| 199 } | |
| 200 | |
| 201 #pragma mark - Testing-Only Methods | |
| 202 | |
| 203 - (scoped_ptr<web::URLFetcherBlockAdapter>) | |
| 204 fetcherForURL:(const GURL&)URL | |
| 205 completionHandler:(web::URLFetcherBlockAdapterCompletion)handler { | |
| 206 return scoped_ptr<web::URLFetcherBlockAdapter>( | |
| 207 new web::URLFetcherBlockAdapter( | |
| 208 URL, _webState->GetBrowserState()->GetRequestContext(), handler)); | |
| 209 } | |
| 210 | |
| 211 @end | |
| OLD | NEW |