Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #import "ios/web/public/web_state/js/crw_js_injection_manager.h" | |
| 6 | |
| 7 #import <UIKit/UIKit.h> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "base/mac/bundle_locations.h" | |
| 11 #import "base/mac/scoped_nsobject.h" | |
| 12 #include "base/strings/sys_string_conversions.h" | |
| 13 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" | |
| 14 | |
| 15 namespace { | |
| 16 // Templete with presence beacon check to prevent re-injection of JavaScript. | |
|
sdefresne
2014/12/10 15:30:23
nit: Templete -> Template.
| |
| 17 NSString* const kPresenceCheckTemplate = @"if (typeof %@ != 'object') { %@}"; | |
|
sdefresne
2014/12/10 15:30:23
nit: @"if (typeof %@ !== 'object') { %@ }";
| |
| 18 } | |
| 19 | |
| 20 @implementation CRWJSInjectionManager { | |
| 21 // JS to inject into the page for our own nefarious purposes. This may be | |
| 22 // nil if it has been purged due to low memory. | |
| 23 base::scoped_nsobject<NSString> _injectObject; | |
| 24 // An object the can receive JavaScript injection. | |
| 25 __weak CRWJSInjectionReceiver* _receiver; | |
| 26 } | |
| 27 | |
| 28 - (id)initWithReceiver:(CRWJSInjectionReceiver*)receiver { | |
| 29 DCHECK(receiver); | |
| 30 self = [super init]; | |
| 31 if (self) { | |
| 32 _receiver = receiver; | |
| 33 // Register for low-memory warnings. | |
| 34 [[NSNotificationCenter defaultCenter] | |
| 35 addObserver:self | |
| 36 selector:@selector(lowMemoryWarning:) | |
| 37 name:UIApplicationDidReceiveMemoryWarningNotification | |
| 38 object:nil]; | |
| 39 } | |
| 40 return self; | |
| 41 } | |
| 42 | |
| 43 - (void)dealloc { | |
| 44 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
| 45 [super dealloc]; | |
| 46 } | |
| 47 | |
| 48 - (BOOL)hasBeenInjected { | |
| 49 DCHECK(self.presenceBeacon); | |
| 50 return [_receiver scriptHasBeenInjectedForClass:[self class] | |
| 51 presenceBeacon:self.presenceBeacon]; | |
| 52 } | |
| 53 | |
| 54 - (void)inject { | |
| 55 if ([self hasBeenInjected]) | |
| 56 return; | |
| 57 [self injectDependenciesIfMissing]; | |
| 58 [_receiver injectScript:[self injectionContent] forClass:[self class]]; | |
| 59 DCHECK([self hasBeenInjected]); | |
| 60 } | |
| 61 | |
| 62 - (NSString*)injectionContentIncludingDependencies { | |
| 63 NSArray* allDependencies = [self allDependencies]; | |
| 64 NSMutableArray* scripts = | |
| 65 [NSMutableArray arrayWithCapacity:allDependencies.count]; | |
| 66 for (CRWJSInjectionManager* dependency in allDependencies) { | |
| 67 [scripts addObject:[dependency injectionContent]]; | |
| 68 } | |
| 69 NSString* script = [scripts componentsJoinedByString:@""]; | |
| 70 NSString* beacon = [self presenceBeacon]; | |
| 71 return [NSString stringWithFormat:kPresenceCheckTemplate, beacon, script]; | |
| 72 } | |
| 73 | |
| 74 - (void)lowMemoryWarning:(NSNotification*)notify { | |
| 75 _injectObject.reset(); | |
| 76 } | |
| 77 | |
| 78 - (void)deferredEvaluate:(NSString*)script { | |
| 79 NSString* deferredScript = [NSString | |
| 80 stringWithFormat:@"window.setTimeout(function() {%@}, 0)", script]; | |
| 81 [self evaluate:deferredScript stringResultHandler:nil]; | |
| 82 } | |
| 83 | |
| 84 - (void)evaluate:(NSString*)script | |
| 85 stringResultHandler:(web::JavaScriptCompletion)completionHandler { | |
| 86 [_receiver evaluateJavaScript:script stringResultHandler:completionHandler]; | |
| 87 } | |
| 88 | |
| 89 - (NSArray*)directDependencies { | |
| 90 return @[]; | |
| 91 } | |
| 92 | |
| 93 - (NSArray*)allDependencies { | |
| 94 NSMutableArray* allDendencies = [NSMutableArray array]; | |
| 95 for (Class dependencyClass in [self directDependencies]) { | |
| 96 CRWJSInjectionManager* dependency = | |
| 97 [_receiver instanceOfClass:dependencyClass]; | |
| 98 NSArray* list = [dependency allDependencies]; | |
| 99 for (CRWJSInjectionManager* manager in list) { | |
| 100 if (![allDendencies containsObject:manager]) | |
| 101 [allDendencies addObject:manager]; | |
| 102 } | |
| 103 } | |
| 104 [allDendencies addObject:self]; | |
| 105 return allDendencies; | |
| 106 } | |
| 107 | |
| 108 #pragma mark - | |
| 109 #pragma mark ProtectedMethods | |
| 110 | |
| 111 - (CRWJSInjectionReceiver*)receiver { | |
| 112 return _receiver; | |
| 113 } | |
| 114 | |
| 115 - (NSString*)scriptPath { | |
| 116 NOTREACHED(); | |
| 117 return nil; | |
| 118 } | |
| 119 | |
| 120 - (NSString*)presenceBeacon { | |
| 121 return nil; | |
| 122 } | |
| 123 | |
| 124 - (NSString*)injectionContent { | |
| 125 if (!_injectObject) | |
| 126 _injectObject.reset([[self staticInjectionContent] copy]); | |
| 127 return _injectObject.get(); | |
| 128 } | |
| 129 | |
| 130 - (NSString*)staticInjectionContent { | |
| 131 DCHECK(self.scriptPath); | |
| 132 NSString* path = [base::mac::FrameworkBundle() pathForResource:self.scriptPath | |
| 133 ofType:@"js"]; | |
| 134 DCHECK(path) << "Script file not found: " | |
| 135 << base::SysNSStringToUTF8(self.scriptPath) << ".js"; | |
| 136 NSError* error = nil; | |
| 137 NSString* content = [NSString stringWithContentsOfFile:path | |
| 138 encoding:NSUTF8StringEncoding | |
| 139 error:&error]; | |
| 140 DCHECK(!error) << "Error fetching script: " << [error.description UTF8String]; | |
| 141 DCHECK(content); | |
| 142 return content; | |
| 143 } | |
| 144 | |
| 145 - (void)injectDependenciesIfMissing { | |
| 146 for (Class dependencyClass in [self directDependencies]) { | |
| 147 CRWJSInjectionManager* dependency = | |
| 148 [_receiver instanceOfClass:dependencyClass]; | |
| 149 [dependency inject]; | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 @end | |
| OLD | NEW |