OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "chrome/browser/ui/cocoa/applescript/tab_applescript.h" | 5 #import "chrome/browser/ui/cocoa/applescript/tab_applescript.h" |
6 | 6 |
7 #import <Carbon/Carbon.h> | 7 #include "base/bind.h" |
8 #import <Foundation/NSAppleEventDescriptor.h> | |
9 | |
10 #include "base/file_path.h" | 8 #include "base/file_path.h" |
11 #include "base/logging.h" | 9 #include "base/logging.h" |
12 #import "base/memory/scoped_nsobject.h" | 10 #import "base/memory/scoped_nsobject.h" |
13 #include "base/sys_string_conversions.h" | 11 #include "base/sys_string_conversions.h" |
14 #include "base/utf_string_conversions.h" | |
15 #include "chrome/browser/printing/print_view_manager.h" | 12 #include "chrome/browser/printing/print_view_manager.h" |
16 #include "chrome/browser/sessions/session_id.h" | 13 #include "chrome/browser/sessions/session_id.h" |
17 #include "chrome/browser/sessions/session_tab_helper.h" | 14 #include "chrome/browser/sessions/session_tab_helper.h" |
| 15 #include "chrome/browser/ui/cocoa/applescript/apple_event_util.h" |
18 #include "chrome/browser/ui/cocoa/applescript/error_applescript.h" | 16 #include "chrome/browser/ui/cocoa/applescript/error_applescript.h" |
19 #include "chrome/common/url_constants.h" | 17 #include "chrome/common/url_constants.h" |
20 #include "content/public/browser/navigation_controller.h" | 18 #include "content/public/browser/navigation_controller.h" |
21 #include "content/public/browser/navigation_entry.h" | 19 #include "content/public/browser/navigation_entry.h" |
22 #include "content/public/browser/render_view_host.h" | 20 #include "content/public/browser/render_view_host.h" |
23 #include "content/public/browser/save_page_type.h" | 21 #include "content/public/browser/save_page_type.h" |
24 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
25 #include "content/public/browser/web_contents_delegate.h" | 23 #include "content/public/browser/web_contents_delegate.h" |
26 #include "googleurl/src/gurl.h" | 24 #include "googleurl/src/gurl.h" |
27 | 25 |
28 using content::NavigationController; | 26 using content::NavigationController; |
29 using content::NavigationEntry; | 27 using content::NavigationEntry; |
30 using content::OpenURLParams; | 28 using content::OpenURLParams; |
31 using content::RenderViewHost; | 29 using content::RenderViewHost; |
32 using content::Referrer; | 30 using content::Referrer; |
33 using content::WebContents; | 31 using content::WebContents; |
34 | 32 |
35 @interface AnyResultValue : NSObject { | 33 namespace { |
36 @private | |
37 scoped_nsobject<NSAppleEventDescriptor> descriptor; | |
38 } | |
39 - (id)initWithDescriptor:(NSAppleEventDescriptor*)desc; | |
40 - (NSAppleEventDescriptor *)scriptingAnyDescriptor; | |
41 @end | |
42 | 34 |
43 @implementation AnyResultValue | 35 void ResumeAppleEventAndSendReply(NSAppleEventManagerSuspensionID suspension_id, |
| 36 const base::Value* result_value) { |
| 37 NSAppleEventDescriptor* result_descriptor = |
| 38 chrome::mac::ValueToAppleEventDescriptor(result_value); |
44 | 39 |
45 - (id)initWithDescriptor:(NSAppleEventDescriptor*)desc { | 40 NSAppleEventManager* manager = [NSAppleEventManager sharedAppleEventManager]; |
46 if (self = [super init]) { | 41 NSAppleEventDescriptor* reply_event = |
47 descriptor.reset([desc retain]); | 42 [manager replyAppleEventForSuspensionID:suspension_id]; |
48 } | 43 [reply_event setParamDescriptor:result_descriptor |
49 return self; | 44 forKeyword:keyDirectObject]; |
| 45 [manager resumeWithSuspensionID:suspension_id]; |
50 } | 46 } |
51 | 47 |
52 - (NSAppleEventDescriptor *)scriptingAnyDescriptor { | 48 } // namespace |
53 return descriptor.get(); | |
54 } | |
55 | |
56 @end | |
57 | |
58 static NSAppleEventDescriptor* valueToDescriptor(Value* value) { | |
59 NSAppleEventDescriptor* descriptor = nil; | |
60 switch (value->GetType()) { | |
61 case Value::TYPE_NULL: | |
62 descriptor = [NSAppleEventDescriptor | |
63 descriptorWithTypeCode:cMissingValue]; | |
64 break; | |
65 case Value::TYPE_BOOLEAN: { | |
66 bool bool_value; | |
67 value->GetAsBoolean(&bool_value); | |
68 descriptor = [NSAppleEventDescriptor descriptorWithBoolean:bool_value]; | |
69 break; | |
70 } | |
71 case Value::TYPE_INTEGER: { | |
72 int int_value; | |
73 value->GetAsInteger(&int_value); | |
74 descriptor = [NSAppleEventDescriptor descriptorWithInt32:int_value]; | |
75 break; | |
76 } | |
77 case Value::TYPE_DOUBLE: { | |
78 double double_value; | |
79 value->GetAsDouble(&double_value); | |
80 descriptor = [NSAppleEventDescriptor | |
81 descriptorWithDescriptorType:typeIEEE64BitFloatingPoint | |
82 bytes:&double_value | |
83 length:sizeof(double_value)]; | |
84 break; | |
85 } | |
86 case Value::TYPE_STRING: { | |
87 std::string string_value; | |
88 value->GetAsString(&string_value); | |
89 descriptor = [NSAppleEventDescriptor descriptorWithString: | |
90 base::SysUTF8ToNSString(string_value)]; | |
91 break; | |
92 } | |
93 case Value::TYPE_BINARY: | |
94 NOTREACHED(); | |
95 break; | |
96 case Value::TYPE_DICTIONARY: { | |
97 DictionaryValue* dictionary_value = static_cast<DictionaryValue*>(value); | |
98 descriptor = [NSAppleEventDescriptor recordDescriptor]; | |
99 NSAppleEventDescriptor* userRecord = [NSAppleEventDescriptor | |
100 listDescriptor]; | |
101 for (DictionaryValue::key_iterator iter(dictionary_value->begin_keys()); | |
102 iter != dictionary_value->end_keys(); ++iter) { | |
103 Value* item; | |
104 if (dictionary_value->Get(*iter, &item)) { | |
105 [userRecord insertDescriptor:[NSAppleEventDescriptor | |
106 descriptorWithString:base::SysUTF8ToNSString(*iter)] atIndex:0]; | |
107 [userRecord insertDescriptor:valueToDescriptor(item) atIndex:0]; | |
108 } | |
109 } | |
110 // Description of what keyASUserRecordFields does. | |
111 // http://www.mail-archive.com/cocoa-dev%40lists.apple.com/msg40149.html | |
112 [descriptor setDescriptor:userRecord forKeyword:keyASUserRecordFields]; | |
113 break; | |
114 } | |
115 case Value::TYPE_LIST: { | |
116 ListValue* list_value; | |
117 value->GetAsList(&list_value); | |
118 descriptor = [NSAppleEventDescriptor listDescriptor]; | |
119 for (unsigned i = 0; i < list_value->GetSize(); ++i) { | |
120 Value* item; | |
121 list_value->Get(i, &item); | |
122 [descriptor insertDescriptor:valueToDescriptor(item) atIndex:0]; | |
123 } | |
124 break; | |
125 } | |
126 } | |
127 return descriptor; | |
128 } | |
129 | 49 |
130 @interface TabAppleScript() | 50 @interface TabAppleScript() |
131 @property (nonatomic, copy) NSString* tempURL; | 51 @property (nonatomic, copy) NSString* tempURL; |
132 @end | 52 @end |
133 | 53 |
134 @implementation TabAppleScript | 54 @implementation TabAppleScript |
135 | 55 |
136 @synthesize tempURL = tempURL_; | 56 @synthesize tempURL = tempURL_; |
137 | 57 |
138 - (id)init { | 58 - (id)init { |
139 if ((self = [super init])) { | 59 if ((self = [super init])) { |
140 SessionID session; | 60 SessionID session; |
141 SessionID::id_type futureSessionIDOfTab = session.id() + 1; | 61 SessionID::id_type futureSessionIDOfTab = session.id() + 1; |
142 // Holds the SessionID that the new tab is going to get. | 62 // Holds the SessionID that the new tab is going to get. |
143 scoped_nsobject<NSNumber> numID( | 63 scoped_nsobject<NSNumber> numID( |
144 [[NSNumber alloc] | 64 [[NSNumber alloc] initWithInt:futureSessionIDOfTab]); |
145 initWithInt:futureSessionIDOfTab]); | |
146 [self setUniqueID:numID]; | 65 [self setUniqueID:numID]; |
147 } | 66 } |
148 return self; | 67 return self; |
149 } | 68 } |
150 | 69 |
151 - (void)dealloc { | 70 - (void)dealloc { |
152 [tempURL_ release]; | 71 [tempURL_ release]; |
153 [super dealloc]; | 72 [super dealloc]; |
154 } | 73 } |
155 | 74 |
156 - (id)initWithWebContents:(content::WebContents*)webContents { | 75 - (id)initWithWebContents:(content::WebContents*)webContents { |
157 if (!webContents) { | 76 if (!webContents) { |
158 [self release]; | 77 [self release]; |
159 return nil; | 78 return nil; |
160 } | 79 } |
161 | 80 |
162 if ((self = [super init])) { | 81 if ((self = [super init])) { |
163 // It is safe to be weak, if a tab goes away (eg user closing a tab) | 82 // It is safe to be weak; if a tab goes away (e.g. the user closes a tab) |
164 // the applescript runtime calls tabs in AppleScriptWindow and this | 83 // the AppleScript runtime calls tabs in AppleScriptWindow and this |
165 // particular tab is never returned. | 84 // particular tab is never returned. |
166 webContents_ = webContents; | 85 webContents_ = webContents; |
167 SessionTabHelper* session_tab_helper = | 86 SessionTabHelper* session_tab_helper = |
168 SessionTabHelper::FromWebContents(webContents); | 87 SessionTabHelper::FromWebContents(webContents); |
169 scoped_nsobject<NSNumber> numID( | 88 scoped_nsobject<NSNumber> numID( |
170 [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]); | 89 [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]); |
171 [self setUniqueID:numID]; | 90 [self setUniqueID:numID]; |
172 } | 91 } |
173 return self; | 92 return self; |
174 } | 93 } |
175 | 94 |
176 - (void)setWebContents:(content::WebContents*)webContents { | 95 - (void)setWebContents:(content::WebContents*)webContents { |
177 DCHECK(webContents); | 96 DCHECK(webContents); |
178 // It is safe to be weak, if a tab goes away (eg user closing a tab) | 97 // It is safe to be weak; if a tab goes away (e.g. the user closes a tab) |
179 // the applescript runtime calls tabs in AppleScriptWindow and this | 98 // the AppleScript runtime calls tabs in AppleScriptWindow and this |
180 // particular tab is never returned. | 99 // particular tab is never returned. |
181 webContents_ = webContents; | 100 webContents_ = webContents; |
182 SessionTabHelper* session_tab_helper = | 101 SessionTabHelper* session_tab_helper = |
183 SessionTabHelper::FromWebContents(webContents); | 102 SessionTabHelper::FromWebContents(webContents); |
184 scoped_nsobject<NSNumber> numID( | 103 scoped_nsobject<NSNumber> numID( |
185 [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]); | 104 [[NSNumber alloc] initWithInt:session_tab_helper->session_id().id()]); |
186 [self setUniqueID:numID]; | 105 [self setUniqueID:numID]; |
187 | 106 |
188 if ([self tempURL]) | 107 if ([self tempURL]) |
189 [self setURL:[self tempURL]]; | 108 [self setURL:[self tempURL]]; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 } | 314 } |
396 } | 315 } |
397 | 316 |
398 - (id)handlesExecuteJavascriptScriptCommand:(NSScriptCommand*)command { | 317 - (id)handlesExecuteJavascriptScriptCommand:(NSScriptCommand*)command { |
399 RenderViewHost* view = webContents_->GetRenderViewHost(); | 318 RenderViewHost* view = webContents_->GetRenderViewHost(); |
400 if (!view) { | 319 if (!view) { |
401 NOTREACHED(); | 320 NOTREACHED(); |
402 return nil; | 321 return nil; |
403 } | 322 } |
404 | 323 |
| 324 NSAppleEventManager* manager = [NSAppleEventManager sharedAppleEventManager]; |
| 325 NSAppleEventManagerSuspensionID suspensionID = |
| 326 [manager suspendCurrentAppleEvent]; |
| 327 content::RenderViewHost::JavascriptResultCallback callback = |
| 328 base::Bind(&ResumeAppleEventAndSendReply, suspensionID); |
| 329 |
405 string16 script = base::SysNSStringToUTF16( | 330 string16 script = base::SysNSStringToUTF16( |
406 [[command evaluatedArguments] objectForKey:@"javascript"]); | 331 [[command evaluatedArguments] objectForKey:@"javascript"]); |
407 Value* value = view->ExecuteJavascriptAndGetValue(string16(), script); | 332 view->ExecuteJavascriptInWebFrameCallbackResult(string16(), // frame_xpath |
408 NSAppleEventDescriptor* descriptor = valueToDescriptor(value); | 333 script, |
409 return [[[AnyResultValue alloc] initWithDescriptor:descriptor] autorelease]; | 334 callback); |
| 335 |
| 336 return nil; |
410 } | 337 } |
411 | 338 |
412 @end | 339 @end |
OLD | NEW |