| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /// Helper program for killing and resetting all Safari settings to a known | 5 /// Helper program for killing and resetting all Safari settings to a known |
| 6 /// state that works well for testing dart2js output in Safari. | 6 /// state that works well for testing dart2js output in Safari. |
| 7 /// | 7 /// |
| 8 /// Warning: this will delete all your Safari settings and bookmarks. | 8 /// Warning: this will delete all your Safari settings and bookmarks. |
| 9 library testing.reset_safari; | 9 library testing.reset_safari; |
| 10 | 10 |
| 11 import 'dart:async' show Future, Timer; | 11 import 'dart:async' show Future, Timer; |
| 12 | 12 |
| 13 import 'dart:io' show Directory, File, Platform, Process, ProcessResult; | 13 import 'dart:io' show Directory, File, Platform, Process; |
| 14 | 14 |
| 15 const String defaultSafariBundleLocation = "/Applications/Safari.app/"; | 15 const String defaultSafariBundleLocation = "/Applications/Safari.app/"; |
| 16 | 16 |
| 17 const String relativeSafariLocation = "Contents/MacOS/Safari"; | 17 const String relativeSafariLocation = "Contents/MacOS/Safari"; |
| 18 | 18 |
| 19 const String lsofLocation = "/usr/sbin/lsof"; | 19 const String lsofLocation = "/usr/sbin/lsof"; |
| 20 | 20 |
| 21 const String killLocation = "/bin/kill"; | 21 const String killLocation = "/bin/kill"; |
| 22 | 22 |
| 23 const String pkillLocation = "/usr/bin/pkill"; | 23 const String pkillLocation = "/usr/bin/pkill"; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 if (force && testOnly) { | 104 if (force && testOnly) { |
| 105 throw new ArgumentError("[force] and [testOnly] can't both be true."); | 105 throw new ArgumentError("[force] and [testOnly] can't both be true."); |
| 106 } | 106 } |
| 107 if (force) return "-KILL"; | 107 if (force) return "-KILL"; |
| 108 if (testOnly) return "-0"; | 108 if (testOnly) return "-0"; |
| 109 return defaultSignal; | 109 return defaultSignal; |
| 110 } | 110 } |
| 111 | 111 |
| 112 Future<int> kill(List<String> pids, | 112 Future<int> kill(List<String> pids, |
| 113 {bool force: false, bool testOnly: false}) async { | 113 {bool force: false, bool testOnly: false}) async { |
| 114 List<String> arguments = <String>[ | 114 var arguments = [signalArgument("-TERM", force: force, testOnly: testOnly)] |
| 115 signalArgument("-TERM", force: force, testOnly: testOnly) | 115 ..addAll(pids); |
| 116 ]..addAll(pids); | 116 var result = await Process.run(killLocation, arguments); |
| 117 ProcessResult result = await Process.run(killLocation, arguments); | |
| 118 return result.exitCode; | 117 return result.exitCode; |
| 119 } | 118 } |
| 120 | 119 |
| 121 Future<int> pkill(String pattern, | 120 Future<int> pkill(String pattern, |
| 122 {bool force: false, bool testOnly: false}) async { | 121 {bool force: false, bool testOnly: false}) async { |
| 123 List<String> arguments = <String>[ | 122 var arguments = [ |
| 124 signalArgument("-HUP", force: force, testOnly: testOnly), | 123 signalArgument("-HUP", force: force, testOnly: testOnly), |
| 125 pattern | 124 pattern |
| 126 ]; | 125 ]; |
| 127 ProcessResult result = await Process.run(pkillLocation, arguments); | 126 var result = await Process.run(pkillLocation, arguments); |
| 128 return result.exitCode; | 127 return result.exitCode; |
| 129 } | 128 } |
| 130 | 129 |
| 131 Uri validatedBundleName(Uri bundle) { | 130 Uri validatedBundleName(Uri bundle) { |
| 132 if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation); | 131 if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation); |
| 133 if (!bundle.path.endsWith("/")) { | 132 if (!bundle.path.endsWith("/")) { |
| 134 throw new ArgumentError("Bundle ('$bundle') must end with a slash ('/')."); | 133 throw new ArgumentError("Bundle ('$bundle') must end with a slash ('/')."); |
| 135 } | 134 } |
| 136 return bundle; | 135 return bundle; |
| 137 } | 136 } |
| 138 | 137 |
| 139 Future<Null> killSafari({Uri bundle}) async { | 138 Future<Null> killSafari({Uri bundle}) async { |
| 140 bundle = validatedBundleName(bundle); | 139 bundle = validatedBundleName(bundle); |
| 141 Uri safariBinary = bundle.resolve(relativeSafariLocation); | 140 var safariBinary = bundle.resolve(relativeSafariLocation); |
| 142 ProcessResult result = | 141 var result = |
| 143 await Process.run(lsofLocation, ["-t", safariBinary.toFilePath()]); | 142 await Process.run(lsofLocation, ["-t", safariBinary.toFilePath()]); |
| 144 if (result.exitCode == 0) { | 143 if (result.exitCode == 0) { |
| 145 String stdout = result.stdout; | 144 var stdout = result.stdout as String; |
| 146 List<String> pids = new List<String>.from( | 145 var pids = |
| 147 stdout.split("\n").where((String line) => !line.isEmpty)); | 146 stdout.split("\n").where((String line) => !line.isEmpty).toList(); |
| 148 Timer timer = new Timer(const Duration(seconds: 10), () { | 147 var timer = new Timer(const Duration(seconds: 10), () { |
| 149 print("Kill -9 Safari $pids"); | 148 print("Kill -9 Safari $pids"); |
| 150 kill(pids, force: true); | 149 kill(pids, force: true); |
| 151 }); | 150 }); |
| 152 int exitCode = await kill(pids); | 151 var exitCode = await kill(pids); |
| 153 while (exitCode == 0) { | 152 while (exitCode == 0) { |
| 154 await pollDelay; | 153 await pollDelay; |
| 155 print("Polling Safari $pids"); | 154 print("Polling Safari $pids"); |
| 156 exitCode = await kill(pids, testOnly: true); | 155 exitCode = await kill(pids, testOnly: true); |
| 157 } | 156 } |
| 158 timer.cancel(); | 157 timer.cancel(); |
| 159 } | 158 } |
| 160 Timer timer = new Timer(const Duration(seconds: 10), () { | 159 var timer = new Timer(const Duration(seconds: 10), () { |
| 161 print("Kill -9 $safari"); | 160 print("Kill -9 $safari"); |
| 162 pkill(safari, force: true); | 161 pkill(safari, force: true); |
| 163 }); | 162 }); |
| 164 int exitCode = await pkill(safari); | 163 var exitCode = await pkill(safari); |
| 165 while (exitCode == 0) { | 164 while (exitCode == 0) { |
| 166 await pollDelay; | 165 await pollDelay; |
| 167 print("Polling $safari"); | 166 print("Polling $safari"); |
| 168 exitCode = await pkill(safari, testOnly: true); | 167 exitCode = await pkill(safari, testOnly: true); |
| 169 } | 168 } |
| 170 timer.cancel(); | 169 timer.cancel(); |
| 171 } | 170 } |
| 172 | 171 |
| 173 Future<Null> deleteIfExists(Uri uri) async { | 172 Future<Null> deleteIfExists(Uri uri) async { |
| 174 Directory directory = new Directory.fromUri(uri); | 173 var directory = new Directory.fromUri(uri); |
| 175 if (await directory.exists()) { | 174 if (await directory.exists()) { |
| 176 print("Deleting directory '$uri'."); | 175 print("Deleting directory '$uri'."); |
| 177 await directory.delete(recursive: true); | 176 await directory.delete(recursive: true); |
| 178 } else { | 177 } else { |
| 179 File file = new File.fromUri(uri); | 178 var file = new File.fromUri(uri); |
| 180 if (await file.exists()) { | 179 if (await file.exists()) { |
| 181 print("Deleting file '$uri'."); | 180 print("Deleting file '$uri'."); |
| 182 await file.delete(); | 181 await file.delete(); |
| 183 } else { | 182 } else { |
| 184 print("File '$uri' not found."); | 183 print("File '$uri' not found."); |
| 185 } | 184 } |
| 186 } | 185 } |
| 187 } | 186 } |
| 188 | 187 |
| 189 Future<Null> resetSafariSettings() async { | 188 Future<Null> resetSafariSettings() async { |
| 190 String home = Platform.environment["HOME"]; | 189 var home = Platform.environment["HOME"]; |
| 191 if (!home.endsWith("/")) { | 190 if (!home.endsWith("/")) { |
| 192 home = "$home/"; | 191 home = "$home/"; |
| 193 } | 192 } |
| 194 Uri homeDirectory = Uri.base.resolve(home); | 193 var homeDirectory = Uri.base.resolve(home); |
| 195 for (String setting in safariSettings) { | 194 for (String setting in safariSettings) { |
| 196 await deleteIfExists(homeDirectory.resolve(setting)); | 195 await deleteIfExists(homeDirectory.resolve(setting)); |
| 197 } | 196 } |
| 198 ProcessResult result = await Process | 197 var result = await Process |
| 199 .run(defaultsLocation, <String>["write", safari, knownSafariPreference]); | 198 .run(defaultsLocation, <String>["write", safari, knownSafariPreference]); |
| 200 if (result.exitCode != 0) { | 199 if (result.exitCode != 0) { |
| 201 throw "Unable to reset Safari settings: ${result.stdout}${result.stderr}"; | 200 throw "Unable to reset Safari settings: ${result.stdout}${result.stderr}"; |
| 202 } | 201 } |
| 203 } | 202 } |
| 204 | 203 |
| 205 Future<Null> killAndResetSafari({Uri bundle}) async { | 204 Future<Null> killAndResetSafari({Uri bundle}) async { |
| 206 bundle = validatedBundleName(bundle); | 205 bundle = validatedBundleName(bundle); |
| 207 await killSafari(bundle: bundle); | 206 await killSafari(bundle: bundle); |
| 208 await resetSafariSettings(); | 207 await resetSafariSettings(); |
| 209 } | 208 } |
| 210 | 209 |
| 211 Future<Null> main() async { | 210 Future<Null> main() async { |
| 212 await killAndResetSafari(); | 211 await killAndResetSafari(); |
| 213 } | 212 } |
| OLD | NEW |