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