Home | History | Annotate | Download | only in applescript
      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