Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / applescript / tab_applescript.mm
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/tab_applescript.h"
6
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #import "base/mac/scoped_nsobject.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "chrome/browser/printing/print_view_manager.h"
13 #include "chrome/browser/sessions/session_tab_helper.h"
14 #include "chrome/browser/ui/cocoa/applescript/apple_event_util.h"
15 #include "chrome/browser/ui/cocoa/applescript/error_applescript.h"
16 #include "chrome/common/url_constants.h"
17 #include "components/sessions/session_id.h"
18 #include "content/public/browser/navigation_controller.h"
19 #include "content/public/browser/navigation_entry.h"
20 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/save_page_type.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/browser/web_contents_delegate.h"
25 #include "url/gurl.h"
26
27 using content::NavigationController;
28 using content::NavigationEntry;
29 using content::OpenURLParams;
30 using content::RenderFrameHost;
31 using content::RenderViewHost;
32 using content::Referrer;
33 using content::WebContents;
34
35 namespace {
36
37 void ResumeAppleEventAndSendReply(NSAppleEventManagerSuspensionID suspension_id,
38                                   const base::Value* result_value) {
39   NSAppleEventDescriptor* result_descriptor =
40       chrome::mac::ValueToAppleEventDescriptor(result_value);
41
42   NSAppleEventManager* manager = [NSAppleEventManager sharedAppleEventManager];
43   NSAppleEventDescriptor* reply_event =
44       [manager replyAppleEventForSuspensionID:suspension_id];
45   [reply_event setParamDescriptor:result_descriptor
46                        forKeyword:keyDirectObject];
47   [manager resumeWithSuspensionID:suspension_id];
48 }
49
50 }  // namespace
51
52 @interface TabAppleScript()
53 @property (nonatomic, copy) NSString* tempURL;
54 @end
55
56 @implementation TabAppleScript
57
58 @synthesize tempURL = tempURL_;
59
60 - (id)init {
61   if ((self = [super init])) {
62     SessionID session;
63     SessionID::id_type futureSessionIDOfTab = session.id() + 1;
64     // Holds the SessionID that the new tab is going to get.
65     base::scoped_nsobject<NSNumber> numID(
66         [[NSNumber alloc] initWithInt:futureSessionIDOfTab]);
67     [self setUniqueID:numID];
68   }
69   return self;
70 }
71
72 - (void)dealloc {
73   [tempURL_ release];
74   [super dealloc];
75 }
76
77 - (id)initWithWebContents:(content::WebContents*)webContents {
78   if (!webContents) {
79     [self release];
80     return nil;
81   }
82
83   if ((self = [super init])) {
84     // It is safe to be weak; if a tab goes away (e.g. the user closes a tab)
85     // the AppleScript runtime calls tabs in AppleScriptWindow and this
86     // particular tab is never returned.
87     webContents_ = webContents;
88     SessionTabHelper* session_tab_helper =
89         SessionTabHelper::FromWebContents(webContents);
90     base::scoped_nsobject<NSNumber> numID(
91         [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]);
92     [self setUniqueID:numID];
93   }
94   return self;
95 }
96
97 - (void)setWebContents:(content::WebContents*)webContents {
98   DCHECK(webContents);
99   // It is safe to be weak; if a tab goes away (e.g. the user closes a tab)
100   // the AppleScript runtime calls tabs in AppleScriptWindow and this
101   // particular tab is never returned.
102   webContents_ = webContents;
103   SessionTabHelper* session_tab_helper =
104       SessionTabHelper::FromWebContents(webContents);
105   base::scoped_nsobject<NSNumber> numID(
106       [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]);
107   [self setUniqueID:numID];
108
109   if ([self tempURL])
110     [self setURL:[self tempURL]];
111 }
112
113 - (NSString*)URL {
114   if (!webContents_) {
115     return nil;
116   }
117
118   NavigationEntry* entry = webContents_->GetController().GetActiveEntry();
119   if (!entry) {
120     return nil;
121   }
122   const GURL& url = entry->GetVirtualURL();
123   return base::SysUTF8ToNSString(url.spec());
124 }
125
126 - (void)setURL:(NSString*)aURL {
127   // If a scripter sets a URL before the node is added save it at a temporary
128   // location.
129   if (!webContents_) {
130     [self setTempURL:aURL];
131     return;
132   }
133
134   GURL url(base::SysNSStringToUTF8(aURL));
135   // check for valid url.
136   if (!url.is_empty() && !url.is_valid()) {
137     AppleScript::SetError(AppleScript::errInvalidURL);
138     return;
139   }
140
141   NavigationEntry* entry = webContents_->GetController().GetActiveEntry();
142   if (!entry)
143     return;
144
145   const GURL& previousURL = entry->GetVirtualURL();
146   webContents_->OpenURL(OpenURLParams(
147       url,
148       content::Referrer(previousURL, blink::WebReferrerPolicyDefault),
149       CURRENT_TAB,
150       ui::PAGE_TRANSITION_TYPED,
151       false));
152 }
153
154 - (NSString*)title {
155   NavigationEntry* entry = webContents_->GetController().GetActiveEntry();
156   if (!entry)
157     return nil;
158
159   base::string16 title = entry ? entry->GetTitle() : base::string16();
160   return base::SysUTF16ToNSString(title);
161 }
162
163 - (NSNumber*)loading {
164   BOOL loadingValue = webContents_->IsLoading() ? YES : NO;
165   return [NSNumber numberWithBool:loadingValue];
166 }
167
168 - (void)handlesUndoScriptCommand:(NSScriptCommand*)command {
169   webContents_->Undo();
170 }
171
172 - (void)handlesRedoScriptCommand:(NSScriptCommand*)command {
173   webContents_->Redo();
174 }
175
176 - (void)handlesCutScriptCommand:(NSScriptCommand*)command {
177   webContents_->Cut();
178 }
179
180 - (void)handlesCopyScriptCommand:(NSScriptCommand*)command {
181   webContents_->Copy();
182 }
183
184 - (void)handlesPasteScriptCommand:(NSScriptCommand*)command {
185   webContents_->Paste();
186 }
187
188 - (void)handlesSelectAllScriptCommand:(NSScriptCommand*)command {
189   webContents_->SelectAll();
190 }
191
192 - (void)handlesGoBackScriptCommand:(NSScriptCommand*)command {
193   NavigationController& navigationController = webContents_->GetController();
194   if (navigationController.CanGoBack())
195     navigationController.GoBack();
196 }
197
198 - (void)handlesGoForwardScriptCommand:(NSScriptCommand*)command {
199   NavigationController& navigationController = webContents_->GetController();
200   if (navigationController.CanGoForward())
201     navigationController.GoForward();
202 }
203
204 - (void)handlesReloadScriptCommand:(NSScriptCommand*)command {
205   NavigationController& navigationController = webContents_->GetController();
206   const bool checkForRepost = true;
207   navigationController.Reload(checkForRepost);
208 }
209
210 - (void)handlesStopScriptCommand:(NSScriptCommand*)command {
211   webContents_->Stop();
212 }
213
214 - (void)handlesPrintScriptCommand:(NSScriptCommand*)command {
215   bool initiated =
216       printing::PrintViewManager::FromWebContents(webContents_)->PrintNow();
217   if (!initiated) {
218     AppleScript::SetError(AppleScript::errInitiatePrinting);
219   }
220 }
221
222 - (void)handlesSaveScriptCommand:(NSScriptCommand*)command {
223   NSDictionary* dictionary = [command evaluatedArguments];
224
225   NSURL* fileURL = [dictionary objectForKey:@"File"];
226   // Scripter has not specifed the location at which to save, so we prompt for
227   // it.
228   if (!fileURL) {
229     webContents_->OnSavePage();
230     return;
231   }
232
233   base::FilePath mainFile(base::SysNSStringToUTF8([fileURL path]));
234   // We create a directory path at the folder within which the file exists.
235   // Eg.    if main_file = '/Users/Foo/Documents/Google.html'
236   // then directory_path = '/Users/Foo/Documents/Google_files/'.
237   base::FilePath directoryPath = mainFile.RemoveExtension();
238   directoryPath = directoryPath.InsertBeforeExtension(std::string("_files/"));
239
240   NSString* saveType = [dictionary objectForKey:@"FileType"];
241
242   content::SavePageType savePageType = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
243   if (saveType) {
244     if ([saveType isEqualToString:@"only html"]) {
245       savePageType = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
246     } else if ([saveType isEqualToString:@"complete html"]) {
247       savePageType = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
248     } else {
249       AppleScript::SetError(AppleScript::errInvalidSaveType);
250       return;
251     }
252   }
253
254   webContents_->SavePage(mainFile, directoryPath, savePageType);
255 }
256
257 - (void)handlesCloseScriptCommand:(NSScriptCommand*)command {
258   webContents_->GetDelegate()->CloseContents(webContents_);
259 }
260
261 - (void)handlesViewSourceScriptCommand:(NSScriptCommand*)command {
262   NavigationEntry* entry =
263       webContents_->GetController().GetLastCommittedEntry();
264   if (entry) {
265     webContents_->OpenURL(
266         OpenURLParams(GURL(content::kViewSourceScheme + std::string(":") +
267                            entry->GetURL().spec()),
268                       Referrer(),
269                       NEW_FOREGROUND_TAB,
270                       ui::PAGE_TRANSITION_LINK,
271                       false));
272   }
273 }
274
275 - (id)handlesExecuteJavascriptScriptCommand:(NSScriptCommand*)command {
276   content::RenderFrameHost* frame = webContents_->GetMainFrame();
277   if (!frame) {
278     NOTREACHED();
279     return nil;
280   }
281
282   NSAppleEventManager* manager = [NSAppleEventManager sharedAppleEventManager];
283   NSAppleEventManagerSuspensionID suspensionID =
284       [manager suspendCurrentAppleEvent];
285   content::RenderFrameHost::JavaScriptResultCallback callback =
286       base::Bind(&ResumeAppleEventAndSendReply, suspensionID);
287
288   base::string16 script = base::SysNSStringToUTF16(
289       [[command evaluatedArguments] objectForKey:@"javascript"]);
290   frame->ExecuteJavaScript(script, callback);
291
292   return nil;
293 }
294
295 @end