Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / applescript / tab_applescript.mm
blob7602e394b3a7d32b147fe47170e2db11fbff3836
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.
5 #import "chrome/browser/ui/cocoa/applescript/tab_applescript.h"
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_id.h"
14 #include "chrome/browser/sessions/session_tab_helper.h"
15 #include "chrome/browser/ui/cocoa/applescript/apple_event_util.h"
16 #include "chrome/browser/ui/cocoa/applescript/error_applescript.h"
17 #include "chrome/common/url_constants.h"
18 #include "content/public/browser/navigation_controller.h"
19 #include "content/public/browser/navigation_entry.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/save_page_type.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_delegate.h"
24 #include "url/gurl.h"
26 using content::NavigationController;
27 using content::NavigationEntry;
28 using content::OpenURLParams;
29 using content::RenderViewHost;
30 using content::Referrer;
31 using content::WebContents;
33 namespace {
35 void ResumeAppleEventAndSendReply(NSAppleEventManagerSuspensionID suspension_id,
36                                   const base::Value* result_value) {
37   NSAppleEventDescriptor* result_descriptor =
38       chrome::mac::ValueToAppleEventDescriptor(result_value);
40   NSAppleEventManager* manager = [NSAppleEventManager sharedAppleEventManager];
41   NSAppleEventDescriptor* reply_event =
42       [manager replyAppleEventForSuspensionID:suspension_id];
43   [reply_event setParamDescriptor:result_descriptor
44                        forKeyword:keyDirectObject];
45   [manager resumeWithSuspensionID:suspension_id];
48 }  // namespace
50 @interface TabAppleScript()
51 @property (nonatomic, copy) NSString* tempURL;
52 @end
54 @implementation TabAppleScript
56 @synthesize tempURL = tempURL_;
58 - (id)init {
59   if ((self = [super init])) {
60     SessionID session;
61     SessionID::id_type futureSessionIDOfTab = session.id() + 1;
62     // Holds the SessionID that the new tab is going to get.
63     base::scoped_nsobject<NSNumber> numID(
64         [[NSNumber alloc] initWithInt:futureSessionIDOfTab]);
65     [self setUniqueID:numID];
66   }
67   return self;
70 - (void)dealloc {
71   [tempURL_ release];
72   [super dealloc];
75 - (id)initWithWebContents:(content::WebContents*)webContents {
76   if (!webContents) {
77     [self release];
78     return nil;
79   }
81   if ((self = [super init])) {
82     // It is safe to be weak; if a tab goes away (e.g. the user closes a tab)
83     // the AppleScript runtime calls tabs in AppleScriptWindow and this
84     // particular tab is never returned.
85     webContents_ = webContents;
86     SessionTabHelper* session_tab_helper =
87         SessionTabHelper::FromWebContents(webContents);
88     base::scoped_nsobject<NSNumber> numID(
89         [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]);
90     [self setUniqueID:numID];
91   }
92   return self;
95 - (void)setWebContents:(content::WebContents*)webContents {
96   DCHECK(webContents);
97   // It is safe to be weak; if a tab goes away (e.g. the user closes a tab)
98   // the AppleScript runtime calls tabs in AppleScriptWindow and this
99   // particular tab is never returned.
100   webContents_ = webContents;
101   SessionTabHelper* session_tab_helper =
102       SessionTabHelper::FromWebContents(webContents);
103   base::scoped_nsobject<NSNumber> numID(
104       [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]);
105   [self setUniqueID:numID];
107   if ([self tempURL])
108     [self setURL:[self tempURL]];
111 - (NSString*)URL {
112   if (!webContents_) {
113     return nil;
114   }
116   NavigationEntry* entry = webContents_->GetController().GetActiveEntry();
117   if (!entry) {
118     return nil;
119   }
120   const GURL& url = entry->GetVirtualURL();
121   return base::SysUTF8ToNSString(url.spec());
124 - (void)setURL:(NSString*)aURL {
125   // If a scripter sets a URL before the node is added save it at a temporary
126   // location.
127   if (!webContents_) {
128     [self setTempURL:aURL];
129     return;
130   }
132   GURL url(base::SysNSStringToUTF8(aURL));
133   // check for valid url.
134   if (!url.is_empty() && !url.is_valid()) {
135     AppleScript::SetError(AppleScript::errInvalidURL);
136     return;
137   }
139   NavigationEntry* entry = webContents_->GetController().GetActiveEntry();
140   if (!entry)
141     return;
143   const GURL& previousURL = entry->GetVirtualURL();
144   webContents_->OpenURL(OpenURLParams(
145       url,
146       content::Referrer(previousURL, blink::WebReferrerPolicyDefault),
147       CURRENT_TAB,
148       content::PAGE_TRANSITION_TYPED,
149       false));
152 - (NSString*)title {
153   NavigationEntry* entry = webContents_->GetController().GetActiveEntry();
154   if (!entry)
155     return nil;
157   base::string16 title = entry ? entry->GetTitle() : base::string16();
158   return base::SysUTF16ToNSString(title);
161 - (NSNumber*)loading {
162   BOOL loadingValue = webContents_->IsLoading() ? YES : NO;
163   return [NSNumber numberWithBool:loadingValue];
166 - (void)handlesUndoScriptCommand:(NSScriptCommand*)command {
167   RenderViewHost* view = webContents_->GetRenderViewHost();
168   if (!view) {
169     NOTREACHED();
170     return;
171   }
173   view->Undo();
176 - (void)handlesRedoScriptCommand:(NSScriptCommand*)command {
177   RenderViewHost* view = webContents_->GetRenderViewHost();
178   if (!view) {
179     NOTREACHED();
180     return;
181   }
183   view->Redo();
186 - (void)handlesCutScriptCommand:(NSScriptCommand*)command {
187   RenderViewHost* view = webContents_->GetRenderViewHost();
188   if (!view) {
189     NOTREACHED();
190     return;
191   }
193   view->Cut();
196 - (void)handlesCopyScriptCommand:(NSScriptCommand*)command {
197   RenderViewHost* view = webContents_->GetRenderViewHost();
198   if (!view) {
199     NOTREACHED();
200     return;
201   }
203   view->Copy();
206 - (void)handlesPasteScriptCommand:(NSScriptCommand*)command {
207   RenderViewHost* view = webContents_->GetRenderViewHost();
208   if (!view) {
209     NOTREACHED();
210     return;
211   }
213   view->Paste();
216 - (void)handlesSelectAllScriptCommand:(NSScriptCommand*)command {
217   RenderViewHost* view = webContents_->GetRenderViewHost();
218   if (!view) {
219     NOTREACHED();
220     return;
221   }
223   view->SelectAll();
226 - (void)handlesGoBackScriptCommand:(NSScriptCommand*)command {
227   NavigationController& navigationController = webContents_->GetController();
228   if (navigationController.CanGoBack())
229     navigationController.GoBack();
232 - (void)handlesGoForwardScriptCommand:(NSScriptCommand*)command {
233   NavigationController& navigationController = webContents_->GetController();
234   if (navigationController.CanGoForward())
235     navigationController.GoForward();
238 - (void)handlesReloadScriptCommand:(NSScriptCommand*)command {
239   NavigationController& navigationController = webContents_->GetController();
240   const bool checkForRepost = true;
241   navigationController.Reload(checkForRepost);
244 - (void)handlesStopScriptCommand:(NSScriptCommand*)command {
245   RenderViewHost* view = webContents_->GetRenderViewHost();
246   if (!view) {
247     // We tolerate Stop being called even before a view has been created.
248     // So just log a warning instead of a NOTREACHED().
249     DLOG(WARNING) << "Stop: no view for handle ";
250     return;
251   }
253   view->Stop();
256 - (void)handlesPrintScriptCommand:(NSScriptCommand*)command {
257   bool initiated =
258       printing::PrintViewManager::FromWebContents(webContents_)->PrintNow();
259   if (!initiated) {
260     AppleScript::SetError(AppleScript::errInitiatePrinting);
261   }
264 - (void)handlesSaveScriptCommand:(NSScriptCommand*)command {
265   NSDictionary* dictionary = [command evaluatedArguments];
267   NSURL* fileURL = [dictionary objectForKey:@"File"];
268   // Scripter has not specifed the location at which to save, so we prompt for
269   // it.
270   if (!fileURL) {
271     webContents_->OnSavePage();
272     return;
273   }
275   base::FilePath mainFile(base::SysNSStringToUTF8([fileURL path]));
276   // We create a directory path at the folder within which the file exists.
277   // Eg.    if main_file = '/Users/Foo/Documents/Google.html'
278   // then directory_path = '/Users/Foo/Documents/Google_files/'.
279   base::FilePath directoryPath = mainFile.RemoveExtension();
280   directoryPath = directoryPath.InsertBeforeExtension(std::string("_files/"));
282   NSString* saveType = [dictionary objectForKey:@"FileType"];
284   content::SavePageType savePageType = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
285   if (saveType) {
286     if ([saveType isEqualToString:@"only html"]) {
287       savePageType = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
288     } else if ([saveType isEqualToString:@"complete html"]) {
289       savePageType = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
290     } else {
291       AppleScript::SetError(AppleScript::errInvalidSaveType);
292       return;
293     }
294   }
296   webContents_->SavePage(mainFile, directoryPath, savePageType);
299 - (void)handlesCloseScriptCommand:(NSScriptCommand*)command {
300   webContents_->GetDelegate()->CloseContents(webContents_);
303 - (void)handlesViewSourceScriptCommand:(NSScriptCommand*)command {
304   NavigationEntry* entry =
305       webContents_->GetController().GetLastCommittedEntry();
306   if (entry) {
307     webContents_->OpenURL(
308         OpenURLParams(GURL(content::kViewSourceScheme + std::string(":") +
309                            entry->GetURL().spec()),
310                       Referrer(),
311                       NEW_FOREGROUND_TAB,
312                       content::PAGE_TRANSITION_LINK,
313                       false));
314   }
317 - (id)handlesExecuteJavascriptScriptCommand:(NSScriptCommand*)command {
318   RenderViewHost* view = webContents_->GetRenderViewHost();
319   if (!view) {
320     NOTREACHED();
321     return nil;
322   }
324   NSAppleEventManager* manager = [NSAppleEventManager sharedAppleEventManager];
325   NSAppleEventManagerSuspensionID suspensionID =
326       [manager suspendCurrentAppleEvent];
327   content::RenderViewHost::JavascriptResultCallback callback =
328       base::Bind(&ResumeAppleEventAndSendReply, suspensionID);
330   base::string16 script = base::SysNSStringToUTF16(
331       [[command evaluatedArguments] objectForKey:@"javascript"]);
332   view->ExecuteJavascriptInWebFrameCallbackResult(
333       base::string16(),  // frame_xpath
334       script,
335       callback);
337   return nil;
340 @end