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 // Template with presence beacon check to prevent re-injection of JavaScript. | |
17 NSString* const kPresenceCheckTemplate = @"if (typeof %@ !== 'object') { %@ }"; | |
18 } | |
19 | |
20 @implementation CRWJSInjectionManager { | |
21 // JS to inject into the page for our own nefarious purposes. This may be | |
stuartmorgan
2014/12/11 23:59:38
Let's drop the "for our own nefarious purposes"
| |
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; | |
sdefresne
2014/12/11 15:25:12
nity: __weak is useless here too.
| |
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 |