blob: 9062948e46bc86364f6d6d3a7acb1faed50a88b5 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/ui/cocoa/applescript/window_applescript.h"
#include <memory>
#include "base/logging.h"
#import "base/mac/foundation_util.h"
#import "base/mac/scoped_nsobject.h"
#include "base/time/time.h"
#import "chrome/browser/app_controller_mac.h"
#import "chrome/browser/chrome_browser_application_mac.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/cocoa/applescript/constants_applescript.h"
#include "chrome/browser/ui/cocoa/applescript/error_applescript.h"
#include "chrome/browser/ui/cocoa/applescript/metrics_applescript.h"
#import "chrome/browser/ui/cocoa/applescript/tab_applescript.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/web_contents.h"
@interface WindowAppleScript(WindowAppleScriptPrivateMethods)
// The NSWindow that corresponds to this window.
- (NSWindow*)nativeHandle;
@end
@implementation WindowAppleScript
- (id)init {
// Check which mode to open a new window.
NSScriptCommand* command = [NSScriptCommand currentCommand];
NSString* mode = [[[command evaluatedArguments]
objectForKey:@"KeyDictionary"] objectForKey:@"mode"];
AppController* appDelegate =
base::mac::ObjCCastStrict<AppController>([NSApp delegate]);
Profile* lastProfile = [appDelegate lastProfile];
if (!lastProfile) {
AppleScript::SetError(AppleScript::errGetProfile);
return nil;
}
Profile* profile;
if ([mode isEqualToString:AppleScript::kIncognitoWindowMode]) {
profile = lastProfile->GetOffTheRecordProfile();
}
else if ([mode isEqualToString:AppleScript::kNormalWindowMode] || !mode) {
profile = lastProfile;
} else {
// Mode cannot be anything else
AppleScript::SetError(AppleScript::errInvalidMode);
return nil;
}
// Set the mode to nil, to ensure that it is not set once more.
[[[command evaluatedArguments] objectForKey:@"KeyDictionary"]
setValue:nil forKey:@"mode"];
return [self initWithProfile:profile];
}
- (id)initWithProfile:(Profile*)aProfile {
if (!aProfile) {
[self release];
return nil;
}
if ((self = [super init])) {
browser_ = new Browser(Browser::CreateParams(aProfile, false));
chrome::NewTab(browser_);
browser_->window()->Show();
base::scoped_nsobject<NSNumber> numID(
[[NSNumber alloc] initWithInt:browser_->session_id().id()]);
[self setUniqueID:numID];
}
return self;
}
- (id)initWithBrowser:(Browser*)aBrowser {
if (!aBrowser) {
[self release];
return nil;
}
if ((self = [super init])) {
// It is safe to be weak, if a window goes away (eg user closing a window)
// the applescript runtime calls appleScriptWindows in
// BrowserCrApplication and this particular window is never returned.
browser_ = aBrowser;
base::scoped_nsobject<NSNumber> numID(
[[NSNumber alloc] initWithInt:browser_->session_id().id()]);
[self setUniqueID:numID];
}
return self;
}
- (NSWindow*)nativeHandle {
// window() can be NULL during startup.
if (browser_->window())
return browser_->window()->GetNativeWindow();
return nil;
}
- (NSNumber*)activeTabIndex {
// Note: applescript is 1-based, that is lists begin with index 1.
int activeTabIndex = browser_->tab_strip_model()->active_index() + 1;
if (!activeTabIndex) {
return nil;
}
return [NSNumber numberWithInt:activeTabIndex];
}
- (void)setActiveTabIndex:(NSNumber*)anActiveTabIndex {
// Note: applescript is 1-based, that is lists begin with index 1.
int atIndex = [anActiveTabIndex intValue] - 1;
if (atIndex >= 0 && atIndex < browser_->tab_strip_model()->count())
browser_->tab_strip_model()->ActivateTabAt(atIndex, true);
else
AppleScript::SetError(AppleScript::errInvalidTabIndex);
}
- (NSString*)mode {
Profile* profile = browser_->profile();
if (profile->IsOffTheRecord())
return AppleScript::kIncognitoWindowMode;
return AppleScript::kNormalWindowMode;
}
- (void)setMode:(NSString*)theMode {
// cannot set mode after window is created.
if (theMode) {
AppleScript::SetError(AppleScript::errSetMode);
}
}
- (TabAppleScript*)activeTab {
TabAppleScript* currentTab =
[[[TabAppleScript alloc] initWithWebContents:
browser_->tab_strip_model()->GetActiveWebContents()] autorelease];
[currentTab setContainer:self
property:AppleScript::kTabsProperty];
return currentTab;
}
- (NSArray*)tabs {
TabStripModel* tabStrip = browser_->tab_strip_model();
NSMutableArray* tabs = [NSMutableArray arrayWithCapacity:tabStrip->count()];
for (int i = 0; i < tabStrip->count(); ++i) {
// Check to see if tab is closing.
content::WebContents* webContents = tabStrip->GetWebContentsAt(i);
if (webContents->IsBeingDestroyed()) {
continue;
}
base::scoped_nsobject<TabAppleScript> tab(
[[TabAppleScript alloc] initWithWebContents:webContents]);
[tab setContainer:self
property:AppleScript::kTabsProperty];
[tabs addObject:tab];
}
return tabs;
}
- (void)insertInTabs:(TabAppleScript*)aTab {
// This method gets called when a new tab is created so
// the container and property are set here.
[aTab setContainer:self
property:AppleScript::kTabsProperty];
// Set how long it takes a tab to be created.
base::TimeTicks newTabStartTime = base::TimeTicks::Now();
content::WebContents* contents = chrome::AddSelectedTabWithURL(
browser_,
GURL(chrome::kChromeUINewTabURL),
ui::PAGE_TRANSITION_TYPED);
CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents);
core_tab_helper->set_new_tab_start_time(newTabStartTime);
[aTab setWebContents:contents];
}
- (void)insertInTabs:(TabAppleScript*)aTab atIndex:(int)index {
// This method gets called when a new tab is created so
// the container and property are set here.
[aTab setContainer:self
property:AppleScript::kTabsProperty];
// Set how long it takes a tab to be created.
base::TimeTicks newTabStartTime = base::TimeTicks::Now();
NavigateParams params(browser_, GURL(chrome::kChromeUINewTabURL),
ui::PAGE_TRANSITION_TYPED);
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
params.tabstrip_index = index;
Navigate(&params);
CoreTabHelper* core_tab_helper =
CoreTabHelper::FromWebContents(params.target_contents);
core_tab_helper->set_new_tab_start_time(newTabStartTime);
[aTab setWebContents:params.target_contents];
}
- (void)removeFromTabsAtIndex:(int)index {
if (index < 0 || index >= browser_->tab_strip_model()->count())
return;
browser_->tab_strip_model()->CloseWebContentsAt(
index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
}
- (NSNumber*)orderedIndex {
return [NSNumber numberWithInt:[[self nativeHandle] orderedIndex]];
}
- (void)setOrderedIndex:(NSNumber*)anIndex {
int index = [anIndex intValue] - 1;
if (index < 0 || index >= static_cast<int>(chrome::GetTotalBrowserCount())) {
AppleScript::SetError(AppleScript::errWrongIndex);
return;
}
[[self nativeHandle] setOrderedIndex:index];
}
- (NSComparisonResult)windowComparator:(WindowAppleScript*)otherWindow {
int thisIndex = [[self orderedIndex] intValue];
int otherIndex = [[otherWindow orderedIndex] intValue];
if (thisIndex < otherIndex)
return NSOrderedAscending;
else if (thisIndex > otherIndex)
return NSOrderedDescending;
// Indexes can never be same.
NOTREACHED();
return NSOrderedSame;
}
// Get and set values from the associated NSWindow.
- (id)valueForUndefinedKey:(NSString*)key {
return [[self nativeHandle] valueForKey:key];
}
- (void)setValue:(id)value forUndefinedKey:(NSString*)key {
[[self nativeHandle] setValue:(id)value forKey:key];
}
- (void)handlesCloseScriptCommand:(NSCloseCommand*)command {
AppleScript::LogAppleScriptUMA(AppleScript::AppleScriptCommand::WINDOW_CLOSE);
// window() can be NULL during startup.
if (browser_->window())
browser_->window()->Close();
}
@end