OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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 "chrome/browser/cocoa/external_protocol_dialog.h" |
| 6 |
| 7 #include "app/l10n_util_mac.h" |
| 8 #include "base/message_loop.h" |
| 9 #include "base/sys_string_conversions.h" |
| 10 #include "chrome/browser/external_protocol_handler.h" |
| 11 #include "grit/chromium_strings.h" |
| 12 #include "grit/generated_resources.h" |
| 13 |
| 14 /////////////////////////////////////////////////////////////////////////////// |
| 15 // ExternalProtocolHandler |
| 16 |
| 17 // static |
| 18 void ExternalProtocolHandler::RunExternalProtocolDialog( |
| 19 const GURL& url, int render_process_host_id, int routing_id) { |
| 20 [[ExternalProtocolDialogController alloc] initWithGURL:&url]; |
| 21 } |
| 22 |
| 23 /////////////////////////////////////////////////////////////////////////////// |
| 24 // ExternalProtocolDialogController |
| 25 |
| 26 @interface ExternalProtocolDialogController(Private) |
| 27 - (void)alertEnded:(NSAlert *)alert |
| 28 returnCode:(int)returnCode |
| 29 contextInfo:(void*)contextInfo; |
| 30 - (string16)appNameForProtocol; |
| 31 @end |
| 32 |
| 33 @implementation ExternalProtocolDialogController |
| 34 - (id)initWithGURL:(const GURL*)url { |
| 35 DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()); |
| 36 |
| 37 url_ = *url; |
| 38 creation_time_ = base::Time::Now(); |
| 39 |
| 40 string16 appName = [self appNameForProtocol]; |
| 41 if (appName.length() == 0) { |
| 42 // No registered apps for this protocol; give up and go home. |
| 43 [self autorelease]; |
| 44 return nil; |
| 45 } |
| 46 |
| 47 alert_ = [[NSAlert alloc] init]; |
| 48 |
| 49 [alert_ setMessageText: |
| 50 l10n_util::GetNSStringWithFixup(IDS_EXTERNAL_PROTOCOL_TITLE)]; |
| 51 |
| 52 NSButton* allowButton = [alert_ addButtonWithTitle: |
| 53 l10n_util::GetNSStringWithFixup(IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT)]; |
| 54 [allowButton setKeyEquivalent:@""]; // disallow as default |
| 55 [alert_ addButtonWithTitle: |
| 56 l10n_util::GetNSStringWithFixup(IDS_CANCEL)]; |
| 57 |
| 58 NSString* urlString = l10n_util::GetNSStringFWithFixup( |
| 59 IDS_EXTERNAL_PROTOCOL_INFORMATION, |
| 60 ASCIIToUTF16(url_.scheme() + ":"), |
| 61 ASCIIToUTF16(url_.possibly_invalid_spec())); |
| 62 NSString* appString = l10n_util::GetNSStringFWithFixup( |
| 63 IDS_EXTERNAL_PROTOCOL_APPLICATION_TO_LAUNCH, |
| 64 appName); |
| 65 NSString* warningString = |
| 66 l10n_util::GetNSStringWithFixup(IDS_EXTERNAL_PROTOCOL_WARNING); |
| 67 NSString* informativeText = |
| 68 [NSString stringWithFormat:@"%@\n\n%@\n\n%@", |
| 69 urlString, |
| 70 appString, |
| 71 warningString]; |
| 72 |
| 73 [alert_ setInformativeText:informativeText]; |
| 74 |
| 75 [alert_ setShowsSuppressionButton:YES]; |
| 76 [[alert_ suppressionButton] setTitle: |
| 77 l10n_util::GetNSStringWithFixup(IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT)]; |
| 78 |
| 79 [alert_ beginSheetModalForWindow:nil // nil here makes it app-modal |
| 80 modalDelegate:self |
| 81 didEndSelector:@selector(alertEnded:returnCode:contextInfo:) |
| 82 contextInfo:nil]; |
| 83 |
| 84 return self; |
| 85 } |
| 86 |
| 87 - (void)dealloc { |
| 88 [alert_ release]; |
| 89 |
| 90 [super dealloc]; |
| 91 } |
| 92 |
| 93 - (void)alertEnded:(NSAlert *)alert |
| 94 returnCode:(int)returnCode |
| 95 contextInfo:(void*)contextInfo { |
| 96 ExternalProtocolHandler::BlockState blockState = |
| 97 ExternalProtocolHandler::UNKNOWN; |
| 98 switch (returnCode) { |
| 99 case NSAlertFirstButtonReturn: |
| 100 blockState = ExternalProtocolHandler::DONT_BLOCK; |
| 101 break; |
| 102 case NSAlertSecondButtonReturn: |
| 103 blockState = ExternalProtocolHandler::BLOCK; |
| 104 break; |
| 105 default: |
| 106 NOTREACHED(); |
| 107 } |
| 108 |
| 109 // Set the "don't warn me again" info if the protocol was blocked ("cancel" |
| 110 // always means "make this dialog go away with no permanent effect" no matter |
| 111 // what). |
| 112 if ([[alert_ suppressionButton] state] == NSOnState && |
| 113 blockState == ExternalProtocolHandler::BLOCK) { |
| 114 ExternalProtocolHandler::SetBlockState(UTF8ToWide(url_.scheme()), |
| 115 blockState); |
| 116 } |
| 117 |
| 118 if (blockState == ExternalProtocolHandler::DONT_BLOCK) { |
| 119 UMA_HISTOGRAM_LONG_TIMES("clickjacking.launch_url", |
| 120 base::Time::Now() - creation_time_); |
| 121 |
| 122 ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_); |
| 123 } |
| 124 |
| 125 [self autorelease]; |
| 126 } |
| 127 |
| 128 - (string16)appNameForProtocol { |
| 129 NSURL* url = [NSURL URLWithString: |
| 130 base::SysUTF8ToNSString(url_.possibly_invalid_spec())]; |
| 131 CFURLRef openingApp = NULL; |
| 132 OSStatus status = LSGetApplicationForURL((CFURLRef)url, |
| 133 kLSRolesAll, |
| 134 NULL, |
| 135 &openingApp); |
| 136 if (status != noErr) { |
| 137 // likely kLSApplicationNotFoundErr |
| 138 return string16(); |
| 139 } |
| 140 NSString* appPath = [(NSURL*)openingApp path]; |
| 141 CFRelease(openingApp); // NOT A BUG; LSGetApplicationForURL retains for us |
| 142 NSString* appDisplayName = |
| 143 [[NSFileManager defaultManager] displayNameAtPath:appPath]; |
| 144 |
| 145 return base::SysNSStringToUTF16(appDisplayName); |
| 146 } |
| 147 |
| 148 @end |
OLD | NEW |