| 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 | |
| 6 /// 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 |
| 7 /// state that works well for testing dart2js output in Safari. | 6 /// state that works well for testing dart2js output in Safari. |
| 8 /// | 7 /// |
| 9 /// Warning: this will delete all your Safari settings and bookmarks. | 8 /// Warning: this will delete all your Safari settings and bookmarks. |
| 10 library testing.reset_safari; | 9 library testing.reset_safari; |
| 11 | 10 |
| 12 import 'dart:async' show | 11 import 'dart:async' show Future, Timer; |
| 13 Future, | |
| 14 Timer; | |
| 15 | 12 |
| 16 import 'dart:io' show | 13 import 'dart:io' show Directory, File, Platform, Process, ProcessResult; |
| 17 Directory, | |
| 18 File, | |
| 19 Platform, | |
| 20 Process, | |
| 21 ProcessResult; | |
| 22 | 14 |
| 23 const String defaultSafariBundleLocation = "/Applications/Safari.app/"; | 15 const String defaultSafariBundleLocation = "/Applications/Safari.app/"; |
| 24 | 16 |
| 25 const String relativeSafariLocation = "Contents/MacOS/Safari"; | 17 const String relativeSafariLocation = "Contents/MacOS/Safari"; |
| 26 | 18 |
| 27 const String lsofLocation = "/usr/sbin/lsof"; | 19 const String lsofLocation = "/usr/sbin/lsof"; |
| 28 | 20 |
| 29 const String killLocation = "/bin/kill"; | 21 const String killLocation = "/bin/kill"; |
| 30 | 22 |
| 31 const String pkillLocation = "/usr/bin/pkill"; | 23 const String pkillLocation = "/usr/bin/pkill"; |
| 32 | 24 |
| 33 const String safari = "com.apple.Safari"; | 25 const String safari = "com.apple.Safari"; |
| 34 | 26 |
| 35 const String defaultsLocation = "/usr/bin/defaults"; | 27 const String defaultsLocation = "/usr/bin/defaults"; |
| 36 | 28 |
| 37 final List<String> safariSettings = <String>[ | 29 final List<String> safariSettings = <String>[ |
| 38 "Library/Caches/$safari", | 30 "Library/Caches/$safari", |
| 39 "Library/Safari", | 31 "Library/Safari", |
| 40 "Library/Saved Application State/$safari.savedState", | 32 "Library/Saved Application State/$safari.savedState", |
| 41 "Library/Caches/Metadata/Safari", | 33 "Library/Caches/Metadata/Safari", |
| 42 "Library/Preferences/$safari.plist", | 34 "Library/Preferences/$safari.plist", |
| 43 ]; | 35 ]; |
| 44 | 36 |
| 45 const Duration defaultPollDelay = const Duration(milliseconds: 1); | 37 const Duration defaultPollDelay = const Duration(milliseconds: 1); |
| 46 | 38 |
| 47 final String cpgi = "$safari.ContentPageGroupIdentifier"; | 39 final String cpgi = "$safari.ContentPageGroupIdentifier"; |
| 48 | 40 |
| 49 final String knownSafariPreference = ''' | 41 final String knownSafariPreference = ''' |
| 50 { | 42 { |
| 51 DefaultBrowserPromptingState2 = 2; | 43 DefaultBrowserPromptingState2 = 2; |
| 52 StartPageViewControllerMode = 0; | 44 StartPageViewControllerMode = 0; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 InstallExtensionUpdatesAutomatically = 0; | 92 InstallExtensionUpdatesAutomatically = 0; |
| 101 | 93 |
| 102 ShowFullURLInSmartSearchField = 1; | 94 ShowFullURLInSmartSearchField = 1; |
| 103 | 95 |
| 104 "$cpgi.WebKit2PlugInSnapshottingEnabled" = 0; | 96 "$cpgi.WebKit2PlugInSnapshottingEnabled" = 0; |
| 105 } | 97 } |
| 106 '''; | 98 '''; |
| 107 | 99 |
| 108 Future<Null> get pollDelay => new Future.delayed(defaultPollDelay); | 100 Future<Null> get pollDelay => new Future.delayed(defaultPollDelay); |
| 109 | 101 |
| 110 String signalArgument( | 102 String signalArgument(String defaultSignal, |
| 111 String defaultSignal, | 103 {bool force: false, bool testOnly: false}) { |
| 112 {bool force: false, | |
| 113 bool testOnly: false}) { | |
| 114 if (force && testOnly) { | 104 if (force && testOnly) { |
| 115 throw new ArgumentError("[force] and [testOnly] can't both be true."); | 105 throw new ArgumentError("[force] and [testOnly] can't both be true."); |
| 116 } | 106 } |
| 117 if (force) return "-KILL"; | 107 if (force) return "-KILL"; |
| 118 if (testOnly) return "-0"; | 108 if (testOnly) return "-0"; |
| 119 return defaultSignal; | 109 return defaultSignal; |
| 120 } | 110 } |
| 121 | 111 |
| 122 Future<int> kill( | 112 Future<int> kill(List<String> pids, |
| 123 List<String> pids, | 113 {bool force: false, bool testOnly: false}) async { |
| 124 {bool force: false, | 114 List<String> arguments = <String>[ |
| 125 bool testOnly: false}) async { | 115 signalArgument("-TERM", force: force, testOnly: testOnly) |
| 126 List<String> arguments = | 116 ]..addAll(pids); |
| 127 <String>[signalArgument("-TERM", force: force, testOnly: testOnly)] | |
| 128 ..addAll(pids); | |
| 129 ProcessResult result = await Process.run(killLocation, arguments); | 117 ProcessResult result = await Process.run(killLocation, arguments); |
| 130 return result.exitCode; | 118 return result.exitCode; |
| 131 } | 119 } |
| 132 | 120 |
| 133 Future<int> pkill( | 121 Future<int> pkill(String pattern, |
| 134 String pattern, | 122 {bool force: false, bool testOnly: false}) async { |
| 135 {bool force: false, | |
| 136 bool testOnly: false}) async { | |
| 137 List<String> arguments = <String>[ | 123 List<String> arguments = <String>[ |
| 138 signalArgument("-HUP", force: force, testOnly: testOnly), | 124 signalArgument("-HUP", force: force, testOnly: testOnly), |
| 139 pattern]; | 125 pattern |
| 126 ]; |
| 140 ProcessResult result = await Process.run(pkillLocation, arguments); | 127 ProcessResult result = await Process.run(pkillLocation, arguments); |
| 141 return result.exitCode; | 128 return result.exitCode; |
| 142 } | 129 } |
| 143 | 130 |
| 144 Uri validatedBundleName(Uri bundle) { | 131 Uri validatedBundleName(Uri bundle) { |
| 145 if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation); | 132 if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation); |
| 146 if (!bundle.path.endsWith("/")) { | 133 if (!bundle.path.endsWith("/")) { |
| 147 throw new ArgumentError( | 134 throw new ArgumentError("Bundle ('$bundle') must end with a slash ('/')."); |
| 148 "Bundle ('$bundle') must end with a slash ('/')."); | |
| 149 } | 135 } |
| 150 return bundle; | 136 return bundle; |
| 151 } | 137 } |
| 152 | 138 |
| 153 Future<Null> killSafari({Uri bundle}) async { | 139 Future<Null> killSafari({Uri bundle}) async { |
| 154 bundle = validatedBundleName(bundle); | 140 bundle = validatedBundleName(bundle); |
| 155 Uri safariBinary = bundle.resolve(relativeSafariLocation); | 141 Uri safariBinary = bundle.resolve(relativeSafariLocation); |
| 156 ProcessResult result = await Process.run( | 142 ProcessResult result = |
| 157 lsofLocation, ["-t", safariBinary.toFilePath()]); | 143 await Process.run(lsofLocation, ["-t", safariBinary.toFilePath()]); |
| 158 if (result.exitCode == 0) { | 144 if (result.exitCode == 0) { |
| 159 String stdout = result.stdout; | 145 String stdout = result.stdout; |
| 160 List<String> pids = new List<String>.from( | 146 List<String> pids = new List<String>.from( |
| 161 stdout.split("\n").where((String line) => !line.isEmpty)); | 147 stdout.split("\n").where((String line) => !line.isEmpty)); |
| 162 Timer timer = new Timer(const Duration(seconds: 10), () { | 148 Timer timer = new Timer(const Duration(seconds: 10), () { |
| 163 print("Kill -9 Safari $pids"); | 149 print("Kill -9 Safari $pids"); |
| 164 kill(pids, force: true); | 150 kill(pids, force: true); |
| 165 }); | 151 }); |
| 166 int exitCode = await kill(pids); | 152 int exitCode = await kill(pids); |
| 167 while (exitCode == 0) { | 153 while (exitCode == 0) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 | 188 |
| 203 Future<Null> resetSafariSettings() async { | 189 Future<Null> resetSafariSettings() async { |
| 204 String home = Platform.environment["HOME"]; | 190 String home = Platform.environment["HOME"]; |
| 205 if (!home.endsWith("/")) { | 191 if (!home.endsWith("/")) { |
| 206 home = "$home/"; | 192 home = "$home/"; |
| 207 } | 193 } |
| 208 Uri homeDirectory = Uri.base.resolve(home); | 194 Uri homeDirectory = Uri.base.resolve(home); |
| 209 for (String setting in safariSettings) { | 195 for (String setting in safariSettings) { |
| 210 await deleteIfExists(homeDirectory.resolve(setting)); | 196 await deleteIfExists(homeDirectory.resolve(setting)); |
| 211 } | 197 } |
| 212 ProcessResult result = await Process.run( | 198 ProcessResult result = await Process |
| 213 defaultsLocation, <String>["write", safari, knownSafariPreference]); | 199 .run(defaultsLocation, <String>["write", safari, knownSafariPreference]); |
| 214 if (result.exitCode != 0) { | 200 if (result.exitCode != 0) { |
| 215 throw "Unable to reset Safari settings: ${result.stdout}${result.stderr}"; | 201 throw "Unable to reset Safari settings: ${result.stdout}${result.stderr}"; |
| 216 } | 202 } |
| 217 } | 203 } |
| 218 | 204 |
| 219 Future<Null> killAndResetSafari({Uri bundle}) async { | 205 Future<Null> killAndResetSafari({Uri bundle}) async { |
| 220 bundle = validatedBundleName(bundle); | 206 bundle = validatedBundleName(bundle); |
| 221 await killSafari(bundle: bundle); | 207 await killSafari(bundle: bundle); |
| 222 await resetSafariSettings(); | 208 await resetSafariSettings(); |
| 223 } | 209 } |
| 224 | 210 |
| 225 Future<Null> main() async { | 211 Future<Null> main() async { |
| 226 await killAndResetSafari(); | 212 await killAndResetSafari(); |
| 227 } | 213 } |
| OLD | NEW |