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

Side by Side Diff: ios/chrome/today_extension/lock_screen_state.mm

Issue 2586713002: Upstream code and resources for Chrome on iOS extensions. (Closed)
Patch Set: Created 4 years 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
OLDNEW
(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/chrome/today_extension/lock_screen_state.h"
6
7 #import <UIKit/UIKit.h>
8
9 #import "base/ios/weak_nsobject.h"
10
11 namespace {
12
13 // Name of the protected file used to detect if extension is triggered on lock
14 // screen.
15 NSString* const kLockScreenFileName = @"LockScreenDetector";
16
17 // Return the path of a file that will always have NSFileProtectionComplete
18 // protection option. This file cannot be accessed from the lock screen and can
19 // be used to detect if the device is locked.
20 NSString* LockedDeviceFilename() {
21 NSString* path = [NSSearchPathForDirectoriesInDomains(
22 NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
23 return [path stringByAppendingPathComponent:kLockScreenFileName];
24 }
25
26 } // namespace
27
28 @interface LockScreenState ()
29
30 - (instancetype)init;
31
32 // Returns if the protected file is accessible.
33 // Note: the function tests the access to protected file. Access is revoked 10
34 // seconds after screen is locked. So this method returns YES if screen has been
35 // locked for more than 10 seconds.
36 // Returns NO if CreateLockScreenDetector has never been called.
37 - (BOOL)isProtectedFileAccessible;
38
39 // Periodically checks (every second) if the protected file is still accessible.
40 // Checks |remainingTests| times.
41 - (void)recheckProtectedFile:(int)remainingTests;
42
43 // Creates a protected file that will be used to detect if screen is locked.
44 - (void)createLockScreenDetector;
45
46 @end
47
48 @implementation LockScreenState {
49 id<LockScreenStateDelegate> _delegate;
50 BOOL _screenLocked;
51 BOOL _lockScreenStateKnown;
52 BOOL _protectedFileCreated;
53 }
54
55 - (instancetype)init {
56 self = [super init];
57 if (self) {
58 [[NSNotificationCenter defaultCenter]
59 addObserver:self
60 selector:@selector(screenLocked:)
61 name:UIApplicationProtectedDataWillBecomeUnavailable
62 object:nil];
63 [[NSNotificationCenter defaultCenter]
64 addObserver:self
65 selector:@selector(screenUnlocked:)
66 name:UIApplicationProtectedDataDidBecomeAvailable
67 object:nil];
68 _delegate = nil;
69 }
70 return self;
71 }
72
73 + (instancetype)sharedInstance {
74 static LockScreenState* instance = [[LockScreenState alloc] init];
75 return instance;
76 }
77
78 - (void)screenLocked:(id)arguments {
79 _screenLocked = YES;
80 _lockScreenStateKnown = YES;
81 [_delegate lockScreenStateDidChange:self];
82 }
83
84 - (void)screenUnlocked:(id)arguments {
85 _screenLocked = NO;
86 _lockScreenStateKnown = YES;
87 [_delegate lockScreenStateDidChange:self];
88 }
89
90 - (void)setDelegate:(id)delegate {
91 _delegate = delegate;
92 }
93
94 - (BOOL)isScreenLocked {
95 if (_lockScreenStateKnown) {
96 return _screenLocked;
97 }
98 [self createLockScreenDetector];
99 if (!_protectedFileCreated) {
100 // File could not be created. Screen is locked.
101 _screenLocked = YES;
102 _lockScreenStateKnown = YES;
103 return YES;
104 }
105 _screenLocked = ![self isProtectedFileAccessible];
106 _lockScreenStateKnown = YES;
107
108 if (!_screenLocked) {
109 // This test is only valid if screen has been locked for more than 10
110 // seconds (https://www.apple.com/business/docs/iOS_Security_Guide.pdf).
111 // In that case, no notification is received after the delay.
112 // Reschedule tests every second for 15 seconds.
113 base::WeakNSObject<LockScreenState> weakSelf(self);
114 dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
115 static_cast<int64_t>(1 * NSEC_PER_SEC)),
116 dispatch_get_main_queue(), ^{
117 [weakSelf recheckProtectedFile:14];
118 });
119 }
120 return _screenLocked;
121 }
122
123 - (void)recheckProtectedFile:(int)remainingTests {
124 BOOL screenLocked = ![self isProtectedFileAccessible];
125 if (screenLocked) {
126 // |_screenLocked| may already be set to YES if we received a notification.
127 if (!_screenLocked) {
128 _screenLocked = YES;
129 [_delegate lockScreenStateDidChange:self];
130 }
131 return;
132 }
133 if (remainingTests) {
134 base::WeakNSObject<LockScreenState> weakSelf(self);
135 dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
136 static_cast<int64_t>(1 * NSEC_PER_SEC)),
137 dispatch_get_main_queue(), ^{
138 [weakSelf recheckProtectedFile:remainingTests - 1];
139 });
140 }
141 }
142
143 - (BOOL)isProtectedFileAccessible {
144 NSError* error = nil;
145 if (![[NSFileManager defaultManager]
146 fileExistsAtPath:LockedDeviceFilename()]) {
147 return NO;
148 }
149 [NSData dataWithContentsOfFile:LockedDeviceFilename()
150 options:NSDataReadingMappedIfSafe
151 error:&error];
152 return !error;
153 }
154
155 - (void)createLockScreenDetector {
156 if (_protectedFileCreated)
157 return;
158 NSError* error = nil;
159 if ([[NSFileManager defaultManager]
160 fileExistsAtPath:LockedDeviceFilename()]) {
161 NSDictionary* attributes = [[NSFileManager defaultManager]
162 attributesOfItemAtPath:LockedDeviceFilename()
163 error:&error];
164 if ([[attributes valueForKey:NSFileProtectionKey]
165 isEqualToString:NSFileProtectionComplete]) {
166 _protectedFileCreated = YES;
167 return;
168 }
169 BOOL removed =
170 [[NSFileManager defaultManager] removeItemAtPath:LockedDeviceFilename()
171 error:&error];
172 if (!removed || error) {
173 // File could not be removed. FileSystem may be locked ?
174 return;
175 }
176 }
177 BOOL created = [[NSFileManager defaultManager]
178 createFileAtPath:LockedDeviceFilename()
179 contents:[@"Unlock" dataUsingEncoding:NSUTF8StringEncoding]
180 attributes:@{NSFileProtectionKey : NSFileProtectionComplete}];
181 if (!created) {
182 // File could not be created. FileSystem may be locked ?
183 return;
184 }
185 NSDictionary* attributes = [[NSFileManager defaultManager]
186 attributesOfItemAtPath:LockedDeviceFilename()
187 error:&error];
188 if ([[attributes valueForKey:NSFileProtectionKey]
189 isEqualToString:NSFileProtectionComplete]) {
190 _protectedFileCreated = YES;
191 return;
192 }
193 [[NSFileManager defaultManager] removeItemAtPath:LockedDeviceFilename()
194 error:&error];
195 }
196
197 @end
OLDNEW
« no previous file with comments | « ios/chrome/today_extension/lock_screen_state.h ('k') | ios/chrome/today_extension/notification_center_button.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698