tab_applescript.mm revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2010 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/tab_applescript.h"
6
7#include "base/file_path.h"
8#include "base/logging.h"
9#import "base/scoped_nsobject.h"
10#include "base/sys_string_conversions.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/download/save_package.h"
13#include "chrome/browser/sessions/session_id.h"
14#include "chrome/browser/ui/cocoa/applescript/error_applescript.h"
15#include "chrome/common/url_constants.h"
16#include "content/browser/renderer_host/render_view_host.h"
17#include "content/browser/tab_contents/navigation_controller.h"
18#include "content/browser/tab_contents/navigation_entry.h"
19#include "content/browser/tab_contents/tab_contents.h"
20#include "googleurl/src/gurl.h"
21
22@interface TabAppleScript()
23@property (nonatomic, copy) NSString* tempURL;
24@end
25
26@implementation TabAppleScript
27
28@synthesize tempURL = tempURL_;
29
30- (id)init {
31  if ((self = [super init])) {
32    SessionID session;
33    SessionID::id_type futureSessionIDOfTab = session.id() + 1;
34    // Holds the SessionID that the new tab is going to get.
35    scoped_nsobject<NSNumber> numID(
36        [[NSNumber alloc]
37            initWithInt:futureSessionIDOfTab]);
38    [self setUniqueID:numID];
39    [self setTempURL:@""];
40  }
41  return self;
42}
43
44- (void)dealloc {
45  [tempURL_ release];
46  [super dealloc];
47}
48
49- (id)initWithTabContent:(TabContents*)aTabContent {
50  if (!aTabContent) {
51    [self release];
52    return nil;
53  }
54
55  if ((self = [super init])) {
56    // It is safe to be weak, if a tab goes away (eg user closing a tab)
57    // the applescript runtime calls tabs in AppleScriptWindow and this
58    // particular tab is never returned.
59    tabContents_ = aTabContent;
60    scoped_nsobject<NSNumber> numID(
61        [[NSNumber alloc]
62            initWithInt:tabContents_->controller().session_id().id()]);
63    [self setUniqueID:numID];
64  }
65  return self;
66}
67
68- (void)setTabContent:(TabContents*)aTabContent {
69  DCHECK(aTabContent);
70  // It is safe to be weak, if a tab goes away (eg user closing a tab)
71  // the applescript runtime calls tabs in AppleScriptWindow and this
72  // particular tab is never returned.
73  tabContents_ = aTabContent;
74  scoped_nsobject<NSNumber> numID(
75      [[NSNumber alloc]
76          initWithInt:tabContents_->controller().session_id().id()]);
77  [self setUniqueID:numID];
78
79  [self setURL:[self tempURL]];
80}
81
82- (NSString*)URL {
83  if (!tabContents_) {
84    return nil;
85  }
86
87  NavigationEntry* entry = tabContents_->controller().GetActiveEntry();
88  if (!entry) {
89    return nil;
90  }
91  const GURL& url = entry->virtual_url();
92  return base::SysUTF8ToNSString(url.spec());
93}
94
95- (void)setURL:(NSString*)aURL {
96  // If a scripter sets a URL before the node is added save it at a temporary
97  // location.
98  if (!tabContents_) {
99    [self setTempURL:aURL];
100    return;
101  }
102
103  GURL url(base::SysNSStringToUTF8(aURL));
104  // check for valid url.
105  if (!url.is_empty() && !url.is_valid()) {
106    AppleScript::SetError(AppleScript::errInvalidURL);
107    return;
108  }
109
110  NavigationEntry* entry = tabContents_->controller().GetActiveEntry();
111  if (!entry)
112    return;
113
114  const GURL& previousURL = entry->virtual_url();
115  tabContents_->OpenURL(url,
116                        previousURL,
117                        CURRENT_TAB,
118                        PageTransition::TYPED);
119}
120
121- (NSString*)title {
122  NavigationEntry* entry = tabContents_->controller().GetActiveEntry();
123  if (!entry)
124    return nil;
125
126  std::wstring title;
127  if (entry != NULL) {
128    title = UTF16ToWideHack(entry->title());
129  }
130
131  return base::SysWideToNSString(title);
132}
133
134- (NSNumber*)loading {
135  BOOL loadingValue = tabContents_->is_loading() ? YES : NO;
136  return [NSNumber numberWithBool:loadingValue];
137}
138
139- (void)handlesUndoScriptCommand:(NSScriptCommand*)command {
140  RenderViewHost* view = tabContents_->render_view_host();
141  if (!view) {
142    NOTREACHED();
143    return;
144  }
145
146  view->Undo();
147}
148
149- (void)handlesRedoScriptCommand:(NSScriptCommand*)command {
150  RenderViewHost* view = tabContents_->render_view_host();
151  if (!view) {
152    NOTREACHED();
153    return;
154  }
155
156  view->Redo();
157}
158
159- (void)handlesCutScriptCommand:(NSScriptCommand*)command {
160  RenderViewHost* view = tabContents_->render_view_host();
161  if (!view) {
162    NOTREACHED();
163    return;
164  }
165
166  view->Cut();
167}
168
169- (void)handlesCopyScriptCommand:(NSScriptCommand*)command {
170  RenderViewHost* view = tabContents_->render_view_host();
171  if (!view) {
172    NOTREACHED();
173    return;
174  }
175
176  view->Copy();
177}
178
179- (void)handlesPasteScriptCommand:(NSScriptCommand*)command {
180  RenderViewHost* view = tabContents_->render_view_host();
181  if (!view) {
182    NOTREACHED();
183    return;
184  }
185
186  view->Paste();
187}
188
189- (void)handlesSelectAllScriptCommand:(NSScriptCommand*)command {
190  RenderViewHost* view = tabContents_->render_view_host();
191  if (!view) {
192    NOTREACHED();
193    return;
194  }
195
196  view->SelectAll();
197}
198
199- (void)handlesGoBackScriptCommand:(NSScriptCommand*)command {
200  NavigationController& navigationController = tabContents_->controller();
201  if (navigationController.CanGoBack())
202    navigationController.GoBack();
203}
204
205- (void)handlesGoForwardScriptCommand:(NSScriptCommand*)command {
206  NavigationController& navigationController = tabContents_->controller();
207  if (navigationController.CanGoForward())
208    navigationController.GoForward();
209}
210
211- (void)handlesReloadScriptCommand:(NSScriptCommand*)command {
212  NavigationController& navigationController = tabContents_->controller();
213  const bool checkForRepost = true;
214  navigationController.Reload(checkForRepost);
215}
216
217- (void)handlesStopScriptCommand:(NSScriptCommand*)command {
218  RenderViewHost* view = tabContents_->render_view_host();
219  if (!view) {
220    // We tolerate Stop being called even before a view has been created.
221    // So just log a warning instead of a NOTREACHED().
222    DLOG(WARNING) << "Stop: no view for handle ";
223    return;
224  }
225
226  view->Stop();
227}
228
229- (void)handlesPrintScriptCommand:(NSScriptCommand*)command {
230  bool initiateStatus = tabContents_->PrintNow();
231  if (initiateStatus == false) {
232    AppleScript::SetError(AppleScript::errInitiatePrinting);
233  }
234}
235
236- (void)handlesSaveScriptCommand:(NSScriptCommand*)command {
237  NSDictionary* dictionary = [command evaluatedArguments];
238
239  NSURL* fileURL = [dictionary objectForKey:@"File"];
240  // Scripter has not specifed the location at which to save, so we prompt for
241  // it.
242  if (!fileURL) {
243    tabContents_->OnSavePage();
244    return;
245  }
246
247  FilePath mainFile(base::SysNSStringToUTF8([fileURL path]));
248  // We create a directory path at the folder within which the file exists.
249  // Eg.    if main_file = '/Users/Foo/Documents/Google.html'
250  // then directory_path = '/Users/Foo/Documents/Google_files/'.
251  FilePath directoryPath = mainFile.RemoveExtension();
252  directoryPath = directoryPath.InsertBeforeExtension(std::string("_files/"));
253
254  NSString* saveType = [dictionary objectForKey:@"FileType"];
255
256  SavePackage::SavePackageType savePackageType =
257      SavePackage::SAVE_AS_COMPLETE_HTML;
258  if (saveType) {
259    if ([saveType isEqualToString:@"only html"]) {
260      savePackageType = SavePackage::SAVE_AS_ONLY_HTML;
261    } else if ([saveType isEqualToString:@"complete html"]) {
262      savePackageType = SavePackage::SAVE_AS_COMPLETE_HTML;
263    } else {
264      AppleScript::SetError(AppleScript::errInvalidSaveType);
265      return;
266    }
267  }
268
269  tabContents_->SavePage(mainFile, directoryPath, savePackageType);
270}
271
272
273- (void)handlesViewSourceScriptCommand:(NSScriptCommand*)command {
274  NavigationEntry* entry = tabContents_->controller().GetLastCommittedEntry();
275  if (entry) {
276    tabContents_->OpenURL(GURL(chrome::kViewSourceScheme + std::string(":") +
277        entry->url().spec()), GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
278  }
279}
280
281- (id)handlesExecuteJavascriptScriptCommand:(NSScriptCommand*)command {
282  RenderViewHost* view = tabContents_->render_view_host();
283  if (!view) {
284    NOTREACHED();
285    return nil;
286  }
287
288  string16 script = base::SysNSStringToUTF16(
289      [[command evaluatedArguments] objectForKey:@"javascript"]);
290  view->ExecuteJavascriptInWebFrame(string16(), script);
291
292  // TODO(Shreyas): Figure out a way to get the response back.
293  return nil;
294}
295
296@end
297