Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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/web_state/ui/crw_web_controller.h" | 5 #import "ios/web/web_state/ui/crw_web_controller.h" |
| 6 | 6 |
| 7 #import <objc/runtime.h> | 7 #import <objc/runtime.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <cmath> | 10 #include <cmath> |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 // The time of the last page transfer start, measured in seconds since Jan 1 | 234 // The time of the last page transfer start, measured in seconds since Jan 1 |
| 235 // 2001. | 235 // 2001. |
| 236 CFAbsoluteTime _lastTransferTimeInSeconds; | 236 CFAbsoluteTime _lastTransferTimeInSeconds; |
| 237 // Default URL (about:blank). | 237 // Default URL (about:blank). |
| 238 GURL _defaultURL; | 238 GURL _defaultURL; |
| 239 // Show overlay view, don't reload web page. | 239 // Show overlay view, don't reload web page. |
| 240 BOOL _overlayPreviewMode; | 240 BOOL _overlayPreviewMode; |
| 241 // If |YES|, call setSuppressDialogs when core.js is injected into the web | 241 // If |YES|, call setSuppressDialogs when core.js is injected into the web |
| 242 // view. | 242 // view. |
| 243 BOOL _setSuppressDialogsLater; | 243 BOOL _setSuppressDialogsLater; |
| 244 // If |YES|, call setSuppressDialogs when core.js is injected into the web | |
| 245 // view. | |
| 246 BOOL _setNotifyAboutDialogsLater; | |
| 247 // The URL of an expected future recreation of the |webView|. Valid | 244 // The URL of an expected future recreation of the |webView|. Valid |
| 248 // only if the web view was discarded for non-user-visible reasons, such that | 245 // only if the web view was discarded for non-user-visible reasons, such that |
| 249 // if the next load request is for that URL, it should be treated as a | 246 // if the next load request is for that URL, it should be treated as a |
| 250 // reconstruction that should use cache aggressively. | 247 // reconstruction that should use cache aggressively. |
| 251 GURL _expectedReconstructionURL; | 248 GURL _expectedReconstructionURL; |
| 252 | 249 |
| 253 scoped_ptr<web::NewWindowInfo> _externalRequest; | 250 scoped_ptr<web::NewWindowInfo> _externalRequest; |
| 254 | 251 |
| 255 // The WebStateImpl instance associated with this CRWWebController. | 252 // The WebStateImpl instance associated with this CRWWebController. |
| 256 scoped_ptr<WebStateImpl> _webStateImpl; | 253 scoped_ptr<WebStateImpl> _webStateImpl; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 | 423 |
| 427 // Handles 'addPluginPlaceholders' message. | 424 // Handles 'addPluginPlaceholders' message. |
| 428 - (BOOL)handleAddPluginPlaceholdersMessage:(base::DictionaryValue*)message | 425 - (BOOL)handleAddPluginPlaceholdersMessage:(base::DictionaryValue*)message |
| 429 context:(NSDictionary*)context; | 426 context:(NSDictionary*)context; |
| 430 // Handles 'chrome.send' message. | 427 // Handles 'chrome.send' message. |
| 431 - (BOOL)handleChromeSendMessage:(base::DictionaryValue*)message | 428 - (BOOL)handleChromeSendMessage:(base::DictionaryValue*)message |
| 432 context:(NSDictionary*)context; | 429 context:(NSDictionary*)context; |
| 433 // Handles 'console' message. | 430 // Handles 'console' message. |
| 434 - (BOOL)handleConsoleMessage:(base::DictionaryValue*)message | 431 - (BOOL)handleConsoleMessage:(base::DictionaryValue*)message |
| 435 context:(NSDictionary*)context; | 432 context:(NSDictionary*)context; |
| 436 // Handles 'dialog.suppressed' message. | 433 // Handles 'geolocationDialog.suppressed' message. |
| 437 - (BOOL)handleDialogSuppressedMessage:(base::DictionaryValue*)message | 434 - (BOOL)handleGeolocationDialogSuppressedMessage:(base::DictionaryValue*)message |
| 438 context:(NSDictionary*)context; | 435 context:(NSDictionary*)context; |
| 439 // Handles 'document.favicons' message. | 436 // Handles 'document.favicons' message. |
| 440 - (BOOL)handleDocumentFaviconsMessage:(base::DictionaryValue*)message | 437 - (BOOL)handleDocumentFaviconsMessage:(base::DictionaryValue*)message |
| 441 context:(NSDictionary*)context; | 438 context:(NSDictionary*)context; |
| 442 // Handles 'document.submit' message. | 439 // Handles 'document.submit' message. |
| 443 - (BOOL)handleDocumentSubmitMessage:(base::DictionaryValue*)message | 440 - (BOOL)handleDocumentSubmitMessage:(base::DictionaryValue*)message |
| 444 context:(NSDictionary*)context; | 441 context:(NSDictionary*)context; |
| 445 // Handles 'externalRequest' message. | 442 // Handles 'externalRequest' message. |
| 446 - (BOOL)handleExternalRequestMessage:(base::DictionaryValue*)message | 443 - (BOOL)handleExternalRequestMessage:(base::DictionaryValue*)message |
| 447 context:(NSDictionary*)context; | 444 context:(NSDictionary*)context; |
| 448 // Handles 'form.activity' message. | 445 // Handles 'form.activity' message. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 // Transition to fade snapshot overlay. | 511 // Transition to fade snapshot overlay. |
| 515 const NSTimeInterval kSnapshotOverlayTransition = 0.5; | 512 const NSTimeInterval kSnapshotOverlayTransition = 0.5; |
| 516 | 513 |
| 517 } // namespace | 514 } // namespace |
| 518 | 515 |
| 519 @implementation CRWWebController | 516 @implementation CRWWebController |
| 520 | 517 |
| 521 @synthesize webUsageEnabled = _webUsageEnabled; | 518 @synthesize webUsageEnabled = _webUsageEnabled; |
| 522 @synthesize usePlaceholderOverlay = _usePlaceholderOverlay; | 519 @synthesize usePlaceholderOverlay = _usePlaceholderOverlay; |
| 523 @synthesize loadPhase = _loadPhase; | 520 @synthesize loadPhase = _loadPhase; |
| 521 @synthesize suppressDialogs = _suppressDialogs; | |
| 524 | 522 |
| 525 // Implemented by subclasses. | 523 // Implemented by subclasses. |
| 526 @dynamic keyboardDisplayRequiresUserAction; | 524 @dynamic keyboardDisplayRequiresUserAction; |
| 527 | 525 |
| 528 + (instancetype)allocWithZone:(struct _NSZone*)zone { | 526 + (instancetype)allocWithZone:(struct _NSZone*)zone { |
| 529 if (self == [CRWWebController class]) { | 527 if (self == [CRWWebController class]) { |
| 530 // This is an abstract class which should not be instantiated directly. | 528 // This is an abstract class which should not be instantiated directly. |
| 531 // Callers should create concrete subclasses instead. | 529 // Callers should create concrete subclasses instead. |
| 532 NOTREACHED(); | 530 NOTREACHED(); |
| 533 return nil; | 531 return nil; |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 935 return self.webScrollView.contentOffset; | 933 return self.webScrollView.contentOffset; |
| 936 } | 934 } |
| 937 | 935 |
| 938 - (BOOL)atTop { | 936 - (BOOL)atTop { |
| 939 if (!self.webView) | 937 if (!self.webView) |
| 940 return YES; | 938 return YES; |
| 941 UIScrollView* scrollView = self.webScrollView; | 939 UIScrollView* scrollView = self.webScrollView; |
| 942 return scrollView.contentOffset.y == -scrollView.contentInset.top; | 940 return scrollView.contentOffset.y == -scrollView.contentInset.top; |
| 943 } | 941 } |
| 944 | 942 |
| 943 - (void)setSuppressDialogs:(BOOL)flag { | |
|
Jackie Quinn
2016/03/17 17:46:41
why "flag" versus something like "supressDialogs"?
Eugene But (OOO till 7-30)
2016/03/17 17:53:21
|flag| was shorter, but I guess suppressDialogs wo
| |
| 944 _suppressDialogs = flag; | |
| 945 if (self.webView) { | |
| 946 NSString* const kSetSuppressDialogs = [NSString | |
| 947 stringWithFormat:@"__gCrWeb.setSuppressGeolocationDialogs(%d);", flag]; | |
| 948 [self evaluateJavaScript:kSetSuppressDialogs stringResultHandler:nil]; | |
| 949 } else { | |
| 950 _setSuppressDialogsLater = flag; | |
| 951 } | |
| 952 } | |
| 953 | |
| 945 - (void)presentSpoofingError { | 954 - (void)presentSpoofingError { |
| 946 UMA_HISTOGRAM_ENUMERATION("Web.URLVerificationFailure", | 955 UMA_HISTOGRAM_ENUMERATION("Web.URLVerificationFailure", |
| 947 [self webViewDocumentType], | 956 [self webViewDocumentType], |
| 948 web::WEB_VIEW_DOCUMENT_TYPE_COUNT); | 957 web::WEB_VIEW_DOCUMENT_TYPE_COUNT); |
| 949 if (self.webView) { | 958 if (self.webView) { |
| 950 [self removeWebViewAllowingCachedReconstruction:NO]; | 959 [self removeWebViewAllowingCachedReconstruction:NO]; |
| 951 [_delegate presentSpoofingError]; | 960 [_delegate presentSpoofingError]; |
| 952 } | 961 } |
| 953 } | 962 } |
| 954 | 963 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 } | 1056 } |
| 1048 [self injectWindowID]; | 1057 [self injectWindowID]; |
| 1049 } | 1058 } |
| 1050 | 1059 |
| 1051 - (void)injectWindowID { | 1060 - (void)injectWindowID { |
| 1052 if (![_windowIDJSManager hasBeenInjected]) { | 1061 if (![_windowIDJSManager hasBeenInjected]) { |
| 1053 // If the window ID wasn't present, this is a new page. | 1062 // If the window ID wasn't present, this is a new page. |
| 1054 [self setPageChangeProbability:web::PAGE_CHANGE_PROBABILITY_LOW]; | 1063 [self setPageChangeProbability:web::PAGE_CHANGE_PROBABILITY_LOW]; |
| 1055 // Default values for suppressDialogs and notifyAboutDialogs are NO, | 1064 // Default values for suppressDialogs and notifyAboutDialogs are NO, |
| 1056 // so updating them only when necessary is a good optimization. | 1065 // so updating them only when necessary is a good optimization. |
| 1057 if (_setSuppressDialogsLater || _setNotifyAboutDialogsLater) { | 1066 if (_setSuppressDialogsLater) { |
| 1058 [self setSuppressDialogs:_setSuppressDialogsLater | 1067 [self setSuppressDialogs:YES]; |
| 1059 notify:_setNotifyAboutDialogsLater]; | |
| 1060 _setSuppressDialogsLater = NO; | 1068 _setSuppressDialogsLater = NO; |
| 1061 _setNotifyAboutDialogsLater = NO; | |
| 1062 } | 1069 } |
| 1063 | 1070 |
| 1064 [_windowIDJSManager inject]; | 1071 [_windowIDJSManager inject]; |
| 1065 DCHECK([_windowIDJSManager hasBeenInjected]); | 1072 DCHECK([_windowIDJSManager hasBeenInjected]); |
| 1066 } | 1073 } |
| 1067 } | 1074 } |
| 1068 | 1075 |
| 1069 // Set the specified recognizer to take priority over any recognizers in the | 1076 // Set the specified recognizer to take priority over any recognizers in the |
| 1070 // view that have a description containing the specified text fragment. | 1077 // view that have a description containing the specified text fragment. |
| 1071 + (void)requireGestureRecognizerToFail:(UIGestureRecognizer*)recognizer | 1078 + (void)requireGestureRecognizerToFail:(UIGestureRecognizer*)recognizer |
| (...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2007 | 2014 |
| 2008 - (SEL)selectorToHandleJavaScriptCommand:(const std::string&)command { | 2015 - (SEL)selectorToHandleJavaScriptCommand:(const std::string&)command { |
| 2009 static std::map<std::string, SEL>* handlers = nullptr; | 2016 static std::map<std::string, SEL>* handlers = nullptr; |
| 2010 static dispatch_once_t onceToken; | 2017 static dispatch_once_t onceToken; |
| 2011 dispatch_once(&onceToken, ^{ | 2018 dispatch_once(&onceToken, ^{ |
| 2012 handlers = new std::map<std::string, SEL>(); | 2019 handlers = new std::map<std::string, SEL>(); |
| 2013 (*handlers)["addPluginPlaceholders"] = | 2020 (*handlers)["addPluginPlaceholders"] = |
| 2014 @selector(handleAddPluginPlaceholdersMessage:context:); | 2021 @selector(handleAddPluginPlaceholdersMessage:context:); |
| 2015 (*handlers)["chrome.send"] = @selector(handleChromeSendMessage:context:); | 2022 (*handlers)["chrome.send"] = @selector(handleChromeSendMessage:context:); |
| 2016 (*handlers)["console"] = @selector(handleConsoleMessage:context:); | 2023 (*handlers)["console"] = @selector(handleConsoleMessage:context:); |
| 2017 (*handlers)["dialog.suppressed"] = | 2024 (*handlers)["geolocationDialog.suppressed"] = |
| 2018 @selector(handleDialogSuppressedMessage:context:); | 2025 @selector(handleGeolocationDialogSuppressedMessage:context:); |
| 2019 (*handlers)["document.favicons"] = | 2026 (*handlers)["document.favicons"] = |
| 2020 @selector(handleDocumentFaviconsMessage:context:); | 2027 @selector(handleDocumentFaviconsMessage:context:); |
| 2021 (*handlers)["document.retitled"] = | 2028 (*handlers)["document.retitled"] = |
| 2022 @selector(handleDocumentRetitledMessage:context:); | 2029 @selector(handleDocumentRetitledMessage:context:); |
| 2023 (*handlers)["document.submit"] = | 2030 (*handlers)["document.submit"] = |
| 2024 @selector(handleDocumentSubmitMessage:context:); | 2031 @selector(handleDocumentSubmitMessage:context:); |
| 2025 (*handlers)["externalRequest"] = | 2032 (*handlers)["externalRequest"] = |
| 2026 @selector(handleExternalRequestMessage:context:); | 2033 @selector(handleExternalRequestMessage:context:); |
| 2027 (*handlers)["form.activity"] = | 2034 (*handlers)["form.activity"] = |
| 2028 @selector(handleFormActivityMessage:context:); | 2035 @selector(handleFormActivityMessage:context:); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2117 std::string origin; | 2124 std::string origin; |
| 2118 if (!message->GetString("origin", &origin)) { | 2125 if (!message->GetString("origin", &origin)) { |
| 2119 DLOG(WARNING) << "JS message parameter not found: origin"; | 2126 DLOG(WARNING) << "JS message parameter not found: origin"; |
| 2120 return NO; | 2127 return NO; |
| 2121 } | 2128 } |
| 2122 | 2129 |
| 2123 DVLOG(0) << origin << " [" << method << "] " << consoleMessage; | 2130 DVLOG(0) << origin << " [" << method << "] " << consoleMessage; |
| 2124 return YES; | 2131 return YES; |
| 2125 } | 2132 } |
| 2126 | 2133 |
| 2127 - (BOOL)handleDialogSuppressedMessage:(base::DictionaryValue*)message | 2134 - (BOOL)handleGeolocationDialogSuppressedMessage:(base::DictionaryValue*)message |
| 2128 context:(NSDictionary*)context { | 2135 context:(NSDictionary*)context { |
| 2129 if ([_delegate | 2136 [self didSuppressDialog]; |
| 2130 respondsToSelector:@selector(webControllerDidSuppressDialog:)]) { | |
| 2131 [_delegate webControllerDidSuppressDialog:self]; | |
| 2132 } | |
| 2133 return YES; | 2137 return YES; |
| 2134 } | 2138 } |
| 2135 | 2139 |
| 2136 - (BOOL)handleDocumentFaviconsMessage:(base::DictionaryValue*)message | 2140 - (BOOL)handleDocumentFaviconsMessage:(base::DictionaryValue*)message |
| 2137 context:(NSDictionary*)context { | 2141 context:(NSDictionary*)context { |
| 2138 base::ListValue* favicons = nullptr; | 2142 base::ListValue* favicons = nullptr; |
| 2139 if (!message->GetList("favicons", &favicons)) { | 2143 if (!message->GetList("favicons", &favicons)) { |
| 2140 DLOG(WARNING) << "JS message parameter not found: favicons"; | 2144 DLOG(WARNING) << "JS message parameter not found: favicons"; |
| 2141 return NO; | 2145 return NO; |
| 2142 } | 2146 } |
| (...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3180 _placeholderOverlayView.reset(); | 3184 _placeholderOverlayView.reset(); |
| 3181 // There are cases when resetting the contentView, above, may happen after | 3185 // There are cases when resetting the contentView, above, may happen after |
| 3182 // the web view has been created. Re-add it here, rather than | 3186 // the web view has been created. Re-add it here, rather than |
| 3183 // relying on a subsequent call to loadCurrentURLInWebView. | 3187 // relying on a subsequent call to loadCurrentURLInWebView. |
| 3184 if (self.webView) { | 3188 if (self.webView) { |
| 3185 [[self view] addSubview:self.webView]; | 3189 [[self view] addSubview:self.webView]; |
| 3186 } | 3190 } |
| 3187 } | 3191 } |
| 3188 } | 3192 } |
| 3189 | 3193 |
| 3190 - (void)internalSuppressDialogs:(BOOL)suppressFlag notify:(BOOL)notifyFlag { | |
| 3191 NSString* const kSetSuppressDialogs = | |
| 3192 [NSString stringWithFormat:@"__gCrWeb.setSuppressDialogs(%d, %d);", | |
| 3193 suppressFlag, notifyFlag]; | |
| 3194 [self setSuppressDialogsWithHelperScript:kSetSuppressDialogs]; | |
| 3195 } | |
| 3196 | |
| 3197 - (void)setPageDialogOpenPolicy:(web::PageDialogOpenPolicy)policy { | 3194 - (void)setPageDialogOpenPolicy:(web::PageDialogOpenPolicy)policy { |
| 3198 switch (policy) { | 3195 switch (policy) { |
| 3199 case web::DIALOG_POLICY_ALLOW: | 3196 case web::DIALOG_POLICY_ALLOW: |
| 3200 [self setSuppressDialogs:NO notify:NO]; | 3197 [self setSuppressDialogs:NO]; |
| 3201 return; | 3198 return; |
| 3202 case web::DIALOG_POLICY_SUPPRESS: | 3199 case web::DIALOG_POLICY_SUPPRESS: |
| 3203 [self setSuppressDialogs:YES notify:YES]; | 3200 [self setSuppressDialogs:YES]; |
| 3204 return; | 3201 return; |
| 3205 } | 3202 } |
| 3206 NOTREACHED(); | 3203 NOTREACHED(); |
| 3207 } | 3204 } |
| 3208 | 3205 |
| 3209 - (void)setSuppressDialogs:(BOOL)suppressFlag notify:(BOOL)notifyFlag { | |
| 3210 if (self.webView && [_earlyScriptManager hasBeenInjected]) { | |
| 3211 [self internalSuppressDialogs:suppressFlag notify:notifyFlag]; | |
| 3212 } else { | |
| 3213 _setSuppressDialogsLater = suppressFlag; | |
| 3214 _setNotifyAboutDialogsLater = notifyFlag; | |
| 3215 } | |
| 3216 } | |
| 3217 | |
| 3218 #pragma mark - | 3206 #pragma mark - |
| 3219 #pragma mark Session Information | 3207 #pragma mark Session Information |
| 3220 | 3208 |
| 3221 - (CRWSessionController*)sessionController { | 3209 - (CRWSessionController*)sessionController { |
| 3222 return _webStateImpl | 3210 return _webStateImpl |
| 3223 ? _webStateImpl->GetNavigationManagerImpl().GetSessionController() | 3211 ? _webStateImpl->GetNavigationManagerImpl().GetSessionController() |
| 3224 : nil; | 3212 : nil; |
| 3225 } | 3213 } |
| 3226 | 3214 |
| 3227 - (CRWSessionEntry*)currentSessionEntry { | 3215 - (CRWSessionEntry*)currentSessionEntry { |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3611 mainDocumentURL: | 3599 mainDocumentURL: |
| 3612 linkClicked:)]) { | 3600 linkClicked:)]) { |
| 3613 return YES; | 3601 return YES; |
| 3614 } | 3602 } |
| 3615 return [_delegate webController:self | 3603 return [_delegate webController:self |
| 3616 shouldOpenURL:url | 3604 shouldOpenURL:url |
| 3617 mainDocumentURL:mainDocumentURL | 3605 mainDocumentURL:mainDocumentURL |
| 3618 linkClicked:linkClicked]; | 3606 linkClicked:linkClicked]; |
| 3619 } | 3607 } |
| 3620 | 3608 |
| 3609 - (void)didSuppressDialog { | |
| 3610 if ([_delegate respondsToSelector:@selector(webControllerDidSuppressDialog:)]) | |
| 3611 [_delegate webControllerDidSuppressDialog:self]; | |
| 3612 } | |
| 3613 | |
| 3621 - (BOOL)isPutativeMainFrameRequest:(NSURLRequest*)request | 3614 - (BOOL)isPutativeMainFrameRequest:(NSURLRequest*)request |
| 3622 targetFrame:(const web::FrameInfo*)targetFrame { | 3615 targetFrame:(const web::FrameInfo*)targetFrame { |
| 3623 // Determine whether the request is for the main frame using frame info if | 3616 // Determine whether the request is for the main frame using frame info if |
| 3624 // available. In the case of missing frame info, the request is considered to | 3617 // available. In the case of missing frame info, the request is considered to |
| 3625 // have originated from the main frame if either of the following is true: | 3618 // have originated from the main frame if either of the following is true: |
| 3626 // (a) The request's URL matches the request's main document URL | 3619 // (a) The request's URL matches the request's main document URL |
| 3627 // (b) The request's URL resourceSpecifier matches the request's | 3620 // (b) The request's URL resourceSpecifier matches the request's |
| 3628 // mainDocumentURL specifier, as is the case upon redirect from http | 3621 // mainDocumentURL specifier, as is the case upon redirect from http |
| 3629 // App Store links to a URL with itms-apps scheme. This appears to be is | 3622 // App Store links to a URL with itms-apps scheme. This appears to be is |
| 3630 // App Store specific behavior, specially handled by web view. | 3623 // App Store specific behavior, specially handled by web view. |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3844 if ([MIMEType isEqualToString:@"text/html"] || | 3837 if ([MIMEType isEqualToString:@"text/html"] || |
| 3845 [MIMEType isEqualToString:@"application/xhtml+xml"] || | 3838 [MIMEType isEqualToString:@"application/xhtml+xml"] || |
| 3846 [MIMEType isEqualToString:@"application/xml"]) { | 3839 [MIMEType isEqualToString:@"application/xml"]) { |
| 3847 return web::WEB_VIEW_DOCUMENT_TYPE_HTML; | 3840 return web::WEB_VIEW_DOCUMENT_TYPE_HTML; |
| 3848 } | 3841 } |
| 3849 | 3842 |
| 3850 return web::WEB_VIEW_DOCUMENT_TYPE_GENERIC; | 3843 return web::WEB_VIEW_DOCUMENT_TYPE_GENERIC; |
| 3851 } | 3844 } |
| 3852 | 3845 |
| 3853 @end | 3846 @end |
| OLD | NEW |