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

Side by Side Diff: remoting/host/me2me_preference_pane.mm

Issue 10446091: Prompt user before restarting System Preferences. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix if.. brace style Created 8 years, 6 months 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 | Annotate | Revision Log
« no previous file with comments | « remoting/host/me2me_preference_pane.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "remoting/host/me2me_preference_pane.h" 5 #import "remoting/host/me2me_preference_pane.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <CommonCrypto/CommonHMAC.h> 8 #include <CommonCrypto/CommonHMAC.h>
9 #include <launch.h> 9 #include <launch.h>
10 #import <PreferencePanes/PreferencePanes.h> 10 #import <PreferencePanes/PreferencePanes.h>
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 object:nil]; 172 object:nil];
173 173
174 service_status_timer_ = 174 service_status_timer_ =
175 [[NSTimer scheduledTimerWithTimeInterval:2.0 175 [[NSTimer scheduledTimerWithTimeInterval:2.0
176 target:self 176 target:self
177 selector:@selector(refreshServiceStatus:) 177 selector:@selector(refreshServiceStatus:)
178 userInfo:nil 178 userInfo:nil
179 repeats:YES] retain]; 179 repeats:YES] retain];
180 [self updateServiceStatus]; 180 [self updateServiceStatus];
181 [self updateAuthorizationStatus]; 181 [self updateAuthorizationStatus];
182 [self readNewConfig]; 182
183 [self checkInstalledVersion];
184 if (!restart_pending_or_canceled_)
185 [self readNewConfig];
186
183 [self updateUI]; 187 [self updateUI];
184 } 188 }
185 189
190 - (void)didSelect {
191 [self checkInstalledVersion];
192 }
193
186 - (void)willUnselect { 194 - (void)willUnselect {
187 NSDistributedNotificationCenter* center = 195 NSDistributedNotificationCenter* center =
188 [NSDistributedNotificationCenter defaultCenter]; 196 [NSDistributedNotificationCenter defaultCenter];
189 [center removeObserver:self]; 197 [center removeObserver:self];
190 198
191 [service_status_timer_ invalidate]; 199 [service_status_timer_ invalidate];
192 [service_status_timer_ release]; 200 [service_status_timer_ release];
193 service_status_timer_ = nil; 201 service_status_timer_ = nil;
194 if (have_new_config_) { 202 if (have_new_config_)
195 [self notifyPlugin:kUpdateFailedNotificationName]; 203 [self notifyPlugin:kUpdateFailedNotificationName];
196 }
197 } 204 }
198 205
199 - (void)applyConfiguration:(id)sender 206 - (void)applyConfiguration:(id)sender
200 pin:(NSString*)pin { 207 pin:(NSString*)pin {
201 if (!have_new_config_) { 208 if (!have_new_config_) {
202 // It shouldn't be possible to hit the button if there is no config to 209 // It shouldn't be possible to hit the button if there is no config to
203 // apply, but check anyway just in case it happens somehow. 210 // apply, but check anyway just in case it happens somehow.
204 return; 211 return;
205 } 212 }
206 213
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 return; 245 return;
239 } 246 }
240 247
241 // Stop the launchd job. This cannot easily be done by the helper tool, 248 // Stop the launchd job. This cannot easily be done by the helper tool,
242 // since the launchd job runs in the current user's context. 249 // since the launchd job runs in the current user's context.
243 [self sendJobControlMessage:LAUNCH_KEY_STOPJOB]; 250 [self sendJobControlMessage:LAUNCH_KEY_STOPJOB];
244 awaiting_service_stop_ = YES; 251 awaiting_service_stop_ = YES;
245 } 252 }
246 253
247 - (void)onNewConfigFile:(NSNotification*)notification { 254 - (void)onNewConfigFile:(NSNotification*)notification {
248 [self readNewConfig]; 255 [self checkInstalledVersion];
256 if (!restart_pending_or_canceled_)
257 [self readNewConfig];
258
249 [self updateUI]; 259 [self updateUI];
250 } 260 }
251 261
252 - (void)refreshServiceStatus:(NSTimer*)timer { 262 - (void)refreshServiceStatus:(NSTimer*)timer {
253 BOOL was_running = is_service_running_; 263 BOOL was_running = is_service_running_;
254 [self updateServiceStatus]; 264 [self updateServiceStatus];
255 if (awaiting_service_stop_ && !is_service_running_) { 265 if (awaiting_service_stop_ && !is_service_running_) {
256 awaiting_service_stop_ = NO; 266 awaiting_service_stop_ = NO;
257 [self notifyPlugin:kUpdateSucceededNotificationName]; 267 [self notifyPlugin:kUpdateSucceededNotificationName];
258 } 268 }
(...skipping 15 matching lines...) Expand all
274 - (void)updateServiceStatus { 284 - (void)updateServiceStatus {
275 pid_t job_pid = base::mac::PIDForJob(kServiceName); 285 pid_t job_pid = base::mac::PIDForJob(kServiceName);
276 is_service_running_ = (job_pid > 0); 286 is_service_running_ = (job_pid > 0);
277 } 287 }
278 288
279 - (void)updateAuthorizationStatus { 289 - (void)updateAuthorizationStatus {
280 is_pane_unlocked_ = [authorization_view_ updateStatus:authorization_view_]; 290 is_pane_unlocked_ = [authorization_view_ updateStatus:authorization_view_];
281 } 291 }
282 292
283 - (void)readNewConfig { 293 - (void)readNewConfig {
284 if ([self restartPanelIfDifferentVersionInstalled]) {
285 // Don't read any new config if the version is mismatched. Return control
286 // to the main run-loop instead, so the application can be terminated.
287 return;
288 }
289
290 std::string file; 294 std::string file;
291 if (!GetTemporaryConfigFilePath(&file)) { 295 if (!GetTemporaryConfigFilePath(&file)) {
292 LOG(ERROR) << "Failed to get path of configuration data."; 296 LOG(ERROR) << "Failed to get path of configuration data.";
293 [self showError]; 297 [self showError];
294 return; 298 return;
295 } 299 }
296 if (access(file.c_str(), F_OK) != 0) 300 if (access(file.c_str(), F_OK) != 0)
297 return; 301 return;
298 302
299 scoped_ptr<remoting::JsonHostConfig> new_config_( 303 scoped_ptr<remoting::JsonHostConfig> new_config_(
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 [status_message_ setStringValue:message]; 348 [status_message_ setStringValue:message];
345 349
346 std::string email; 350 std::string email;
347 if (config_.get()) { 351 if (config_.get()) {
348 bool result = config_->GetString(remoting::kXmppLoginConfigPath, &email); 352 bool result = config_->GetString(remoting::kXmppLoginConfigPath, &email);
349 353
350 // The config has already been checked by |IsConfigValid|. 354 // The config has already been checked by |IsConfigValid|.
351 DCHECK(result); 355 DCHECK(result);
352 } 356 }
353 357
354 [disable_view_ setEnabled:(is_pane_unlocked_ && is_service_running_)]; 358 [disable_view_ setEnabled:(is_pane_unlocked_ && is_service_running_ &&
355 [confirm_pin_view_ setEnabled:is_pane_unlocked_]; 359 !restart_pending_or_canceled_)];
360 [confirm_pin_view_ setEnabled:(is_pane_unlocked_ &&
361 !restart_pending_or_canceled_)];
356 [confirm_pin_view_ setEmail:base::SysUTF8ToNSString(email)]; 362 [confirm_pin_view_ setEmail:base::SysUTF8ToNSString(email)];
357 NSString* applyButtonText = is_service_running_ ? @"Confirm" : @"Enable"; 363 NSString* applyButtonText = is_service_running_ ? @"Confirm" : @"Enable";
358 [confirm_pin_view_ setButtonText:applyButtonText]; 364 [confirm_pin_view_ setButtonText:applyButtonText];
365
366 if (restart_pending_or_canceled_)
367 [authorization_view_ setEnabled:NO];
359 } 368 }
360 369
361 - (void)showError { 370 - (void)showError {
362 NSAlert* alert = [[NSAlert alloc] init]; 371 NSAlert* alert = [[NSAlert alloc] init];
363 [alert setMessageText:@"An unexpected error occurred."]; 372 [alert setMessageText:@"An unexpected error occurred."];
364 [alert setInformativeText:@"Check the system log for more information."]; 373 [alert setInformativeText:@"Check the system log for more information."];
365 [alert setAlertStyle:NSWarningAlertStyle]; 374 [alert setAlertStyle:NSWarningAlertStyle];
366 [alert beginSheetModalForWindow:[[self mainView] window] 375 [alert beginSheetModalForWindow:[[self mainView] window]
367 modalDelegate:nil 376 modalDelegate:nil
368 didEndSelector:nil 377 didEndSelector:nil
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 531
523 - (void)notifyPlugin:(const char*)message { 532 - (void)notifyPlugin:(const char*)message {
524 NSDistributedNotificationCenter* center = 533 NSDistributedNotificationCenter* center =
525 [NSDistributedNotificationCenter defaultCenter]; 534 [NSDistributedNotificationCenter defaultCenter];
526 NSString* name = [NSString stringWithUTF8String:message]; 535 NSString* name = [NSString stringWithUTF8String:message];
527 [center postNotificationName:name 536 [center postNotificationName:name
528 object:nil 537 object:nil
529 userInfo:nil]; 538 userInfo:nil];
530 } 539 }
531 540
532 - (BOOL)restartPanelIfDifferentVersionInstalled { 541 - (void)checkInstalledVersion {
533 NSBundle* this_bundle = [NSBundle bundleForClass:[self class]]; 542 // There's no point repeating the check if the pane has already been disabled
534 NSDictionary* this_plist = [this_bundle infoDictionary]; 543 // from a previous call to this method. The pane only gets disabled when a
535 NSString* this_version = [this_plist objectForKey:@"CFBundleVersion"]; 544 // version-mismatch has been detected here, so skip the check, but continue to
545 // handle the version-mismatch case.
546 if (!restart_pending_or_canceled_) {
547 NSBundle* this_bundle = [NSBundle bundleForClass:[self class]];
548 NSDictionary* this_plist = [this_bundle infoDictionary];
549 NSString* this_version = [this_plist objectForKey:@"CFBundleVersion"];
536 550
537 NSString* bundle_path = [this_bundle bundlePath]; 551 NSString* bundle_path = [this_bundle bundlePath];
538 NSString* plist_path = 552 NSString* plist_path =
539 [bundle_path stringByAppendingString:@"/Contents/Info.plist"]; 553 [bundle_path stringByAppendingString:@"/Contents/Info.plist"];
540 NSDictionary* disk_plist = 554 NSDictionary* disk_plist =
541 [NSDictionary dictionaryWithContentsOfFile:plist_path]; 555 [NSDictionary dictionaryWithContentsOfFile:plist_path];
542 NSString* disk_version = [disk_plist objectForKey:@"CFBundleVersion"]; 556 NSString* disk_version = [disk_plist objectForKey:@"CFBundleVersion"];
543 557
544 if (disk_version == nil) { 558 if (disk_version == nil) {
545 LOG(ERROR) << "Failed to get installed version information"; 559 LOG(ERROR) << "Failed to get installed version information";
546 [self showError]; 560 [self showError];
547 return NO; 561 return;
562 }
563
564 if ([this_version isEqualToString:disk_version])
565 return;
566
567 restart_pending_or_canceled_ = YES;
568 [self updateUI];
548 } 569 }
549 570
550 if ([this_version isEqualToString:disk_version]) { 571 NSWindow* window = [[self mainView] window];
551 return NO; 572 if (window == nil) {
573 // Defer the alert until |didSelect| is called, which happens just after
574 // the window is created.
575 return;
576 }
577
578 // This alert appears as a sheet over the top of the Chromoting pref-pane,
579 // underneath the title, so it's OK to refer to "this preference pane" rather
580 // than repeat the title "Chromoting" here.
581 NSAlert* alert = [[NSAlert alloc] init];
582 [alert setMessageText:@"System update detected"];
583 [alert setInformativeText:@"To use this preference pane, System Preferences "
584 "needs to be restarted"];
585 [alert addButtonWithTitle:@"OK"];
586 NSButton* cancel_button = [alert addButtonWithTitle:@"Cancel"];
587 [cancel_button setKeyEquivalent:@"\e"];
588 [alert setAlertStyle:NSWarningAlertStyle];
589 [alert beginSheetModalForWindow:window
590 modalDelegate:self
591 didEndSelector:@selector(
592 mismatchAlertDidEnd:returnCode:contextInfo:)
593 contextInfo:nil];
594 [alert release];
595 }
596
597 - (void)mismatchAlertDidEnd:(NSAlert*)alert
598 returnCode:(NSInteger)returnCode
599 contextInfo:(void*)contextInfo {
600 if (returnCode == NSAlertFirstButtonReturn) {
601 // OK was pressed.
602
603 // Dismiss the alert window here, so that the application will respond to
604 // the NSApp terminate: message.
605 [[alert window] orderOut:nil];
606 [self restartSystemPreferences];
552 } else { 607 } else {
553 // Terminate and relaunch System Preferences. 608 // Cancel was pressed.
554 609
555 // TODO(lambroslambrou): Improve this when System Preferences supports 610 // If there is a new config file, delete it and notify the web-app of
556 // dynamic reloading of pref-panes. 611 // failure to apply the config. Otherwise, the web-app will remain in a
557 NSTask* task = [[NSTask alloc] init]; 612 // spinning state until System Preferences eventually gets restarted and
558 NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil]; 613 // the user visits this pane again.
559 [task setLaunchPath:[NSString stringWithUTF8String:kHelperTool]]; 614 std::string file;
560 [task setArguments:arguments]; 615 if (!GetTemporaryConfigFilePath(&file)) {
561 [task setStandardInput:[NSPipe pipe]]; 616 // There's no point in alerting the user here. The same error would
562 [task launch]; 617 // happen when the pane is eventually restarted, so the user would be
563 [task release]; 618 // alerted at that time.
564 [NSApp terminate:nil]; 619 LOG(ERROR) << "Failed to get path of configuration data.";
565 return YES; 620 return;
621 }
622 if (access(file.c_str(), F_OK) != 0)
623 return;
624
625 remove(file.c_str());
626 [self notifyPlugin:kUpdateFailedNotificationName];
566 } 627 }
567 } 628 }
568 629
630 - (void)restartSystemPreferences {
631 NSTask* task = [[NSTask alloc] init];
632 NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil];
633 [task setLaunchPath:[NSString stringWithUTF8String:kHelperTool]];
634 [task setArguments:arguments];
635 [task setStandardInput:[NSPipe pipe]];
636 [task launch];
637 [task release];
638 [NSApp terminate:nil];
639 }
640
569 @end 641 @end
OLDNEW
« no previous file with comments | « remoting/host/me2me_preference_pane.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698