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