1 // Copyright (c) 2011 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/ui/cocoa/applescript/window_applescript.h" 6 7 #include "base/logging.h" 8 #import "base/memory/scoped_nsobject.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/time.h" 11 #import "chrome/browser/app_controller_mac.h" 12 #import "chrome/browser/chrome_browser_application_mac.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/tabs/tab_strip_model.h" 15 #include "chrome/browser/ui/browser.h" 16 #include "chrome/browser/ui/browser_list.h" 17 #include "chrome/browser/ui/browser_navigator.h" 18 #include "chrome/browser/ui/browser_window.h" 19 #include "chrome/browser/ui/cocoa/applescript/constants_applescript.h" 20 #include "chrome/browser/ui/cocoa/applescript/error_applescript.h" 21 #import "chrome/browser/ui/cocoa/applescript/tab_applescript.h" 22 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 23 #include "chrome/common/url_constants.h" 24 #include "content/browser/tab_contents/tab_contents.h" 25 26 @interface WindowAppleScript(WindowAppleScriptPrivateMethods) 27 // The NSWindow that corresponds to this window. 28 - (NSWindow*)nativeHandle; 29 @end 30 31 @implementation WindowAppleScript 32 33 - (id)init { 34 // Check which mode to open a new window. 35 NSScriptCommand* command = [NSScriptCommand currentCommand]; 36 NSString* mode = [[[command evaluatedArguments] 37 objectForKey:@"KeyDictionary"] objectForKey:@"mode"]; 38 AppController* appDelegate = [NSApp delegate]; 39 40 Profile* defaultProfile = [appDelegate defaultProfile]; 41 42 if (!defaultProfile) { 43 AppleScript::SetError(AppleScript::errGetProfile); 44 return nil; 45 } 46 47 Profile* profile; 48 if ([mode isEqualToString:AppleScript::kIncognitoWindowMode]) { 49 profile = defaultProfile->GetOffTheRecordProfile(); 50 } 51 else if ([mode isEqualToString:AppleScript::kNormalWindowMode] || !mode) { 52 profile = defaultProfile; 53 } else { 54 // Mode cannot be anything else 55 AppleScript::SetError(AppleScript::errInvalidMode); 56 return nil; 57 } 58 // Set the mode to nil, to ensure that it is not set once more. 59 [[[command evaluatedArguments] objectForKey:@"KeyDictionary"] 60 setValue:nil forKey:@"mode"]; 61 return [self initWithProfile:profile]; 62 } 63 64 - (id)initWithProfile:(Profile*)aProfile { 65 if (!aProfile) { 66 [self release]; 67 return nil; 68 } 69 70 if ((self = [super init])) { 71 browser_ = Browser::Create(aProfile); 72 browser_->NewTab(); 73 browser_->window()->Show(); 74 scoped_nsobject<NSNumber> numID( 75 [[NSNumber alloc] initWithInt:browser_->session_id().id()]); 76 [self setUniqueID:numID]; 77 } 78 return self; 79 } 80 81 - (id)initWithBrowser:(Browser*)aBrowser { 82 if (!aBrowser) { 83 [self release]; 84 return nil; 85 } 86 87 if ((self = [super init])) { 88 // It is safe to be weak, if a window goes away (eg user closing a window) 89 // the applescript runtime calls appleScriptWindows in 90 // BrowserCrApplication and this particular window is never returned. 91 browser_ = aBrowser; 92 scoped_nsobject<NSNumber> numID( 93 [[NSNumber alloc] initWithInt:browser_->session_id().id()]); 94 [self setUniqueID:numID]; 95 } 96 return self; 97 } 98 99 - (NSWindow*)nativeHandle { 100 // window() can be NULL during startup. 101 if (browser_->window()) 102 return browser_->window()->GetNativeHandle(); 103 return nil; 104 } 105 106 - (NSNumber*)activeTabIndex { 107 // Note: applescript is 1-based, that is lists begin with index 1. 108 int activeTabIndex = browser_->active_index() + 1; 109 if (!activeTabIndex) { 110 return nil; 111 } 112 return [NSNumber numberWithInt:activeTabIndex]; 113 } 114 115 - (void)setActiveTabIndex:(NSNumber*)anActiveTabIndex { 116 // Note: applescript is 1-based, that is lists begin with index 1. 117 int atIndex = [anActiveTabIndex intValue] - 1; 118 if (atIndex >= 0 && atIndex < browser_->tab_count()) 119 browser_->ActivateTabAt(atIndex, true); 120 else 121 AppleScript::SetError(AppleScript::errInvalidTabIndex); 122 } 123 124 - (NSString*)mode { 125 Profile* profile = browser_->profile(); 126 if (profile->IsOffTheRecord()) 127 return AppleScript::kIncognitoWindowMode; 128 return AppleScript::kNormalWindowMode; 129 } 130 131 - (void)setMode:(NSString*)theMode { 132 // cannot set mode after window is created. 133 if (theMode) { 134 AppleScript::SetError(AppleScript::errSetMode); 135 } 136 } 137 138 - (TabAppleScript*)activeTab { 139 TabAppleScript* currentTab = 140 [[[TabAppleScript alloc] 141 initWithTabContent:browser_->GetSelectedTabContentsWrapper()] 142 autorelease]; 143 [currentTab setContainer:self 144 property:AppleScript::kTabsProperty]; 145 return currentTab; 146 } 147 148 - (NSArray*)tabs { 149 NSMutableArray* tabs = [NSMutableArray 150 arrayWithCapacity:browser_->tab_count()]; 151 152 for (int i = 0; i < browser_->tab_count(); ++i) { 153 // Check to see if tab is closing. 154 if (browser_->GetTabContentsAt(i)->is_being_destroyed()) { 155 continue; 156 } 157 158 scoped_nsobject<TabAppleScript> tab( 159 [[TabAppleScript alloc] 160 initWithTabContent:(browser_->GetTabContentsWrapperAt(i))]); 161 [tab setContainer:self 162 property:AppleScript::kTabsProperty]; 163 [tabs addObject:tab]; 164 } 165 return tabs; 166 } 167 168 - (void)insertInTabs:(TabAppleScript*)aTab { 169 // This method gets called when a new tab is created so 170 // the container and property are set here. 171 [aTab setContainer:self 172 property:AppleScript::kTabsProperty]; 173 174 // Set how long it takes a tab to be created. 175 base::TimeTicks newTabStartTime = base::TimeTicks::Now(); 176 TabContentsWrapper* contents = 177 browser_->AddSelectedTabWithURL(GURL(chrome::kChromeUINewTabURL), 178 PageTransition::TYPED); 179 contents->tab_contents()->set_new_tab_start_time(newTabStartTime); 180 [aTab setTabContent:contents]; 181 } 182 183 - (void)insertInTabs:(TabAppleScript*)aTab atIndex:(int)index { 184 // This method gets called when a new tab is created so 185 // the container and property are set here. 186 [aTab setContainer:self 187 property:AppleScript::kTabsProperty]; 188 189 // Set how long it takes a tab to be created. 190 base::TimeTicks newTabStartTime = base::TimeTicks::Now(); 191 browser::NavigateParams params(browser_, 192 GURL(chrome::kChromeUINewTabURL), 193 PageTransition::TYPED); 194 params.disposition = NEW_FOREGROUND_TAB; 195 params.tabstrip_index = index; 196 browser::Navigate(¶ms); 197 params.target_contents->tab_contents()->set_new_tab_start_time( 198 newTabStartTime); 199 200 [aTab setTabContent:params.target_contents]; 201 } 202 203 - (void)removeFromTabsAtIndex:(int)index { 204 browser_->tabstrip_model()->DetachTabContentsAt(index); 205 } 206 207 - (NSNumber*)orderedIndex{ 208 return [NSNumber numberWithInt:[[self nativeHandle] orderedIndex]]; 209 } 210 211 - (void)setOrderedIndex:(NSNumber*)anIndex { 212 int index = [anIndex intValue] - 1; 213 if (index < 0 || index >= (int)BrowserList::size()) { 214 AppleScript::SetError(AppleScript::errWrongIndex); 215 return; 216 } 217 [[self nativeHandle] setOrderedIndex:index]; 218 } 219 220 - (NSComparisonResult)windowComparator:(WindowAppleScript*)otherWindow { 221 int thisIndex = [[self orderedIndex] intValue]; 222 int otherIndex = [[otherWindow orderedIndex] intValue]; 223 if (thisIndex < otherIndex) 224 return NSOrderedAscending; 225 else if (thisIndex > otherIndex) 226 return NSOrderedDescending; 227 // Indexes can never be same. 228 NOTREACHED(); 229 return NSOrderedSame; 230 } 231 232 // Get and set values from the associated NSWindow. 233 - (id)valueForUndefinedKey:(NSString*)key { 234 return [[self nativeHandle] valueForKey:key]; 235 } 236 237 - (void)setValue:(id)value forUndefinedKey:(NSString*)key { 238 [[self nativeHandle] setValue:(id)value forKey:key]; 239 } 240 241 - (void)handlesCloseScriptCommand:(NSCloseCommand*)command { 242 // window() can be NULL during startup. 243 if (browser_->window()) 244 browser_->window()->Close(); 245 } 246 247 @end 248