|
1 /* |
|
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * |
|
8 * 1. Redistributions of source code must retain the above copyright |
|
9 * notice, this list of conditions and the following disclaimer. |
|
10 * 2. Redistributions in binary form must reproduce the above copyright |
|
11 * notice, this list of conditions and the following disclaimer in the |
|
12 * documentation and/or other materials provided with the distribution. |
|
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
|
14 * its contributors may be used to endorse or promote products derived |
|
15 * from this software without specific prior written permission. |
|
16 * |
|
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
|
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #import "WebFrameInternal.h" |
|
30 |
|
31 #import "DOMCSSStyleDeclarationInternal.h" |
|
32 #import "DOMDocumentFragmentInternal.h" |
|
33 #import "DOMDocumentInternal.h" |
|
34 #import "DOMElementInternal.h" |
|
35 #import "DOMHTMLElementInternal.h" |
|
36 #import "DOMNodeInternal.h" |
|
37 #import "DOMRangeInternal.h" |
|
38 #import "WebArchiveInternal.h" |
|
39 #import "WebChromeClient.h" |
|
40 #import "WebDataSourceInternal.h" |
|
41 #import "WebDocumentLoaderMac.h" |
|
42 #import "WebDynamicScrollBarsView.h" |
|
43 #import "WebFrameLoaderClient.h" |
|
44 #import "WebFrameViewInternal.h" |
|
45 #import "WebHTMLView.h" |
|
46 #import "WebHTMLViewInternal.h" |
|
47 #import "WebIconFetcherInternal.h" |
|
48 #import "WebKitStatisticsPrivate.h" |
|
49 #import "WebKitVersionChecks.h" |
|
50 #import "WebNSObjectExtras.h" |
|
51 #import "WebNSURLExtras.h" |
|
52 #import "WebScriptDebugger.h" |
|
53 #import "WebScriptWorldInternal.h" |
|
54 #import "WebViewInternal.h" |
|
55 #import <JavaScriptCore/APICast.h> |
|
56 #import <WebCore/AXObjectCache.h> |
|
57 #import <WebCore/AccessibilityObject.h> |
|
58 #import <WebCore/AnimationController.h> |
|
59 #import <WebCore/CSSMutableStyleDeclaration.h> |
|
60 #import <WebCore/Chrome.h> |
|
61 #import <WebCore/ColorMac.h> |
|
62 #import <WebCore/DOMImplementation.h> |
|
63 #import <WebCore/DocLoader.h> |
|
64 #import <WebCore/DocumentFragment.h> |
|
65 #import <WebCore/EventHandler.h> |
|
66 #import <WebCore/EventNames.h> |
|
67 #import <WebCore/Frame.h> |
|
68 #import <WebCore/FrameLoader.h> |
|
69 #import <WebCore/FrameLoaderStateMachine.h> |
|
70 #import <WebCore/FrameTree.h> |
|
71 #import <WebCore/GraphicsContext.h> |
|
72 #import <WebCore/HTMLFrameOwnerElement.h> |
|
73 #import <WebCore/HistoryItem.h> |
|
74 #import <WebCore/HitTestResult.h> |
|
75 #import <WebCore/LegacyWebArchive.h> |
|
76 #import <WebCore/Page.h> |
|
77 #import <WebCore/PluginData.h> |
|
78 #import <WebCore/PrintContext.h> |
|
79 #import <WebCore/RenderLayer.h> |
|
80 #import <WebCore/RenderPart.h> |
|
81 #import <WebCore/RenderView.h> |
|
82 #import <WebCore/ReplaceSelectionCommand.h> |
|
83 #import <WebCore/RuntimeApplicationChecks.h> |
|
84 #import <WebCore/ScriptValue.h> |
|
85 #import <WebCore/SmartReplace.h> |
|
86 #import <WebCore/SVGSMILElement.h> |
|
87 #import <WebCore/TextIterator.h> |
|
88 #import <WebCore/ThreadCheck.h> |
|
89 #import <WebCore/TypingCommand.h> |
|
90 #import <WebCore/htmlediting.h> |
|
91 #import <WebCore/markup.h> |
|
92 #import <WebCore/visible_units.h> |
|
93 #import <WebKitSystemInterface.h> |
|
94 #import <runtime/JSLock.h> |
|
95 #import <runtime/JSObject.h> |
|
96 #import <runtime/JSValue.h> |
|
97 #import <wtf/CurrentTime.h> |
|
98 |
|
99 using namespace std; |
|
100 using namespace WebCore; |
|
101 using namespace HTMLNames; |
|
102 |
|
103 using JSC::JSGlobalObject; |
|
104 using JSC::JSLock; |
|
105 using JSC::JSValue; |
|
106 using JSC::SilenceAssertionsOnly; |
|
107 |
|
108 /* |
|
109 Here is the current behavior matrix for four types of navigations: |
|
110 |
|
111 Standard Nav: |
|
112 |
|
113 Restore form state: YES |
|
114 Restore scroll and focus state: YES |
|
115 Cache policy: NSURLRequestUseProtocolCachePolicy |
|
116 Add to back/forward list: YES |
|
117 |
|
118 Back/Forward: |
|
119 |
|
120 Restore form state: YES |
|
121 Restore scroll and focus state: YES |
|
122 Cache policy: NSURLRequestReturnCacheDataElseLoad |
|
123 Add to back/forward list: NO |
|
124 |
|
125 Reload (meaning only the reload button): |
|
126 |
|
127 Restore form state: NO |
|
128 Restore scroll and focus state: YES |
|
129 Cache policy: NSURLRequestReloadIgnoringCacheData |
|
130 Add to back/forward list: NO |
|
131 |
|
132 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field): |
|
133 |
|
134 Restore form state: NO |
|
135 Restore scroll and focus state: NO, reset to initial conditions |
|
136 Cache policy: NSURLRequestReloadIgnoringCacheData |
|
137 Add to back/forward list: NO |
|
138 */ |
|
139 |
|
140 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey"; |
|
141 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey"; |
|
142 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey"; |
|
143 |
|
144 NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey"; |
|
145 NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey"; |
|
146 NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey"; |
|
147 NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey"; |
|
148 NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey"; |
|
149 NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey"; |
|
150 NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey"; |
|
151 |
|
152 // FIXME: Remove when this key becomes publicly defined |
|
153 NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface"; |
|
154 |
|
155 @implementation WebFramePrivate |
|
156 |
|
157 - (void)dealloc |
|
158 { |
|
159 [webFrameView release]; |
|
160 |
|
161 delete scriptDebugger; |
|
162 |
|
163 [super dealloc]; |
|
164 } |
|
165 |
|
166 - (void)finalize |
|
167 { |
|
168 delete scriptDebugger; |
|
169 |
|
170 [super finalize]; |
|
171 } |
|
172 |
|
173 - (void)setWebFrameView:(WebFrameView *)v |
|
174 { |
|
175 [v retain]; |
|
176 [webFrameView release]; |
|
177 webFrameView = v; |
|
178 } |
|
179 |
|
180 @end |
|
181 |
|
182 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior) |
|
183 { |
|
184 switch (editableLinkBehavior) { |
|
185 case WebKitEditableLinkDefaultBehavior: |
|
186 return EditableLinkDefaultBehavior; |
|
187 case WebKitEditableLinkAlwaysLive: |
|
188 return EditableLinkAlwaysLive; |
|
189 case WebKitEditableLinkOnlyLiveWithShiftKey: |
|
190 return EditableLinkOnlyLiveWithShiftKey; |
|
191 case WebKitEditableLinkLiveWhenNotFocused: |
|
192 return EditableLinkLiveWhenNotFocused; |
|
193 case WebKitEditableLinkNeverLive: |
|
194 return EditableLinkNeverLive; |
|
195 } |
|
196 ASSERT_NOT_REACHED(); |
|
197 return EditableLinkDefaultBehavior; |
|
198 } |
|
199 |
|
200 WebCore::EditingBehaviorType core(WebKitEditingBehavior behavior) |
|
201 { |
|
202 switch (behavior) { |
|
203 case WebKitEditingMacBehavior: |
|
204 return WebCore::EditingMacBehavior; |
|
205 case WebKitEditingWinBehavior: |
|
206 return WebCore::EditingWindowsBehavior; |
|
207 } |
|
208 ASSERT_NOT_REACHED(); |
|
209 return WebCore::EditingMacBehavior; |
|
210 } |
|
211 |
|
212 TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior) |
|
213 { |
|
214 switch (behavior) { |
|
215 case WebTextDirectionSubmenuNeverIncluded: |
|
216 return TextDirectionSubmenuNeverIncluded; |
|
217 case WebTextDirectionSubmenuAutomaticallyIncluded: |
|
218 return TextDirectionSubmenuAutomaticallyIncluded; |
|
219 case WebTextDirectionSubmenuAlwaysIncluded: |
|
220 return TextDirectionSubmenuAlwaysIncluded; |
|
221 } |
|
222 ASSERT_NOT_REACHED(); |
|
223 return TextDirectionSubmenuNeverIncluded; |
|
224 } |
|
225 |
|
226 @implementation WebFrame (WebInternal) |
|
227 |
|
228 Frame* core(WebFrame *frame) |
|
229 { |
|
230 return frame ? frame->_private->coreFrame : 0; |
|
231 } |
|
232 |
|
233 WebFrame *kit(Frame* frame) |
|
234 { |
|
235 return frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : nil; |
|
236 } |
|
237 |
|
238 Page* core(WebView *webView) |
|
239 { |
|
240 return [webView page]; |
|
241 } |
|
242 |
|
243 WebView *kit(Page* page) |
|
244 { |
|
245 return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : nil; |
|
246 } |
|
247 |
|
248 WebView *getWebView(WebFrame *webFrame) |
|
249 { |
|
250 Frame* coreFrame = core(webFrame); |
|
251 if (!coreFrame) |
|
252 return nil; |
|
253 return kit(coreFrame->page()); |
|
254 } |
|
255 |
|
256 + (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement |
|
257 { |
|
258 WebView *webView = kit(page); |
|
259 |
|
260 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView]; |
|
261 RefPtr<Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame)); |
|
262 [frame release]; |
|
263 frame->_private->coreFrame = coreFrame.get(); |
|
264 |
|
265 coreFrame->tree()->setName(name); |
|
266 if (ownerElement) { |
|
267 ASSERT(ownerElement->document()->frame()); |
|
268 ownerElement->document()->frame()->tree()->appendChild(coreFrame.get()); |
|
269 } |
|
270 |
|
271 coreFrame->init(); |
|
272 |
|
273 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]]; |
|
274 |
|
275 return coreFrame.release(); |
|
276 } |
|
277 |
|
278 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView |
|
279 { |
|
280 [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0]; |
|
281 } |
|
282 |
|
283 + (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView |
|
284 { |
|
285 return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement]; |
|
286 } |
|
287 |
|
288 - (BOOL)_isIncludedInWebKitStatistics |
|
289 { |
|
290 return _private && _private->includedInWebKitStatistics; |
|
291 } |
|
292 |
|
293 - (void)_attachScriptDebugger |
|
294 { |
|
295 ScriptController* scriptController = _private->coreFrame->script(); |
|
296 |
|
297 // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature |
|
298 // if the script debugger is attached before a document is created. These calls use the debuggerWorld(), we will need to pass a world |
|
299 // to be able to debug isolated worlds. |
|
300 if (!scriptController->existingWindowShell(debuggerWorld())) |
|
301 return; |
|
302 |
|
303 JSGlobalObject* globalObject = scriptController->globalObject(debuggerWorld()); |
|
304 if (!globalObject) |
|
305 return; |
|
306 |
|
307 if (_private->scriptDebugger) { |
|
308 ASSERT(_private->scriptDebugger == globalObject->debugger()); |
|
309 return; |
|
310 } |
|
311 |
|
312 _private->scriptDebugger = new WebScriptDebugger(globalObject); |
|
313 } |
|
314 |
|
315 - (void)_detachScriptDebugger |
|
316 { |
|
317 if (!_private->scriptDebugger) |
|
318 return; |
|
319 |
|
320 delete _private->scriptDebugger; |
|
321 _private->scriptDebugger = 0; |
|
322 } |
|
323 |
|
324 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v |
|
325 { |
|
326 self = [super init]; |
|
327 if (!self) |
|
328 return nil; |
|
329 |
|
330 _private = [[WebFramePrivate alloc] init]; |
|
331 |
|
332 // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since |
|
333 // it calls WebFrame _isIncludedInWebKitStatistics. |
|
334 if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics])) |
|
335 ++WebFrameCount; |
|
336 |
|
337 if (fv) { |
|
338 [_private setWebFrameView:fv]; |
|
339 [fv _setWebFrame:self]; |
|
340 } |
|
341 |
|
342 _private->shouldCreateRenderers = YES; |
|
343 |
|
344 return self; |
|
345 } |
|
346 |
|
347 - (void)_clearCoreFrame |
|
348 { |
|
349 _private->coreFrame = 0; |
|
350 } |
|
351 |
|
352 - (void)_updateBackgroundAndUpdatesWhileOffscreen |
|
353 { |
|
354 WebView *webView = getWebView(self); |
|
355 BOOL drawsBackground = [webView drawsBackground]; |
|
356 NSColor *backgroundColor = [webView backgroundColor]; |
|
357 |
|
358 Frame* coreFrame = _private->coreFrame; |
|
359 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { |
|
360 if ([webView _usesDocumentViews]) { |
|
361 // Don't call setDrawsBackground:YES here because it may be NO because of a load |
|
362 // in progress; WebFrameLoaderClient keeps it set to NO during the load process. |
|
363 WebFrame *webFrame = kit(frame); |
|
364 if (!drawsBackground) |
|
365 [[[webFrame frameView] _scrollView] setDrawsBackground:NO]; |
|
366 [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor]; |
|
367 id documentView = [[webFrame frameView] documentView]; |
|
368 if ([documentView respondsToSelector:@selector(setDrawsBackground:)]) |
|
369 [documentView setDrawsBackground:drawsBackground]; |
|
370 if ([documentView respondsToSelector:@selector(setBackgroundColor:)]) |
|
371 [documentView setBackgroundColor:backgroundColor]; |
|
372 } |
|
373 |
|
374 if (FrameView* view = frame->view()) { |
|
375 view->setTransparent(!drawsBackground); |
|
376 view->setBaseBackgroundColor(colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace])); |
|
377 view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]); |
|
378 } |
|
379 } |
|
380 } |
|
381 |
|
382 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate |
|
383 { |
|
384 _private->internalLoadDelegate = internalLoadDelegate; |
|
385 } |
|
386 |
|
387 - (id)_internalLoadDelegate |
|
388 { |
|
389 return _private->internalLoadDelegate; |
|
390 } |
|
391 |
|
392 #ifndef BUILDING_ON_TIGER |
|
393 - (void)_unmarkAllBadGrammar |
|
394 { |
|
395 Frame* coreFrame = _private->coreFrame; |
|
396 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { |
|
397 if (Document* document = frame->document()) |
|
398 document->removeMarkers(DocumentMarker::Grammar); |
|
399 } |
|
400 } |
|
401 #endif |
|
402 |
|
403 - (void)_unmarkAllMisspellings |
|
404 { |
|
405 Frame* coreFrame = _private->coreFrame; |
|
406 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { |
|
407 if (Document* document = frame->document()) |
|
408 document->removeMarkers(DocumentMarker::Spelling); |
|
409 } |
|
410 } |
|
411 |
|
412 - (BOOL)_hasSelection |
|
413 { |
|
414 if ([getWebView(self) _usesDocumentViews]) { |
|
415 id documentView = [_private->webFrameView documentView]; |
|
416 |
|
417 // optimization for common case to avoid creating potentially large selection string |
|
418 if ([documentView isKindOfClass:[WebHTMLView class]]) |
|
419 if (Frame* coreFrame = _private->coreFrame) |
|
420 return coreFrame->selection()->isRange(); |
|
421 |
|
422 if ([documentView conformsToProtocol:@protocol(WebDocumentText)]) |
|
423 return [[documentView selectedString] length] > 0; |
|
424 |
|
425 return NO; |
|
426 } |
|
427 |
|
428 Frame* coreFrame = _private->coreFrame; |
|
429 return coreFrame && coreFrame->selection()->isRange(); |
|
430 } |
|
431 |
|
432 - (void)_clearSelection |
|
433 { |
|
434 ASSERT([getWebView(self) _usesDocumentViews]); |
|
435 id documentView = [_private->webFrameView documentView]; |
|
436 if ([documentView conformsToProtocol:@protocol(WebDocumentText)]) |
|
437 [documentView deselectAll]; |
|
438 } |
|
439 |
|
440 #if !ASSERT_DISABLED |
|
441 - (BOOL)_atMostOneFrameHasSelection |
|
442 { |
|
443 // FIXME: 4186050 is one known case that makes this debug check fail. |
|
444 BOOL found = NO; |
|
445 Frame* coreFrame = _private->coreFrame; |
|
446 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) |
|
447 if ([kit(frame) _hasSelection]) { |
|
448 if (found) |
|
449 return NO; |
|
450 found = YES; |
|
451 } |
|
452 return YES; |
|
453 } |
|
454 #endif |
|
455 |
|
456 - (WebFrame *)_findFrameWithSelection |
|
457 { |
|
458 Frame* coreFrame = _private->coreFrame; |
|
459 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { |
|
460 WebFrame *webFrame = kit(frame); |
|
461 if ([webFrame _hasSelection]) |
|
462 return webFrame; |
|
463 } |
|
464 return nil; |
|
465 } |
|
466 |
|
467 - (void)_clearSelectionInOtherFrames |
|
468 { |
|
469 // We rely on WebDocumentSelection protocol implementors to call this method when they become first |
|
470 // responder. It would be nicer to just notice first responder changes here instead, but there's no |
|
471 // notification sent when the first responder changes in general (Radar 2573089). |
|
472 WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection]; |
|
473 if (frameWithSelection != self) |
|
474 [frameWithSelection _clearSelection]; |
|
475 |
|
476 // While we're in the general area of selection and frames, check that there is only one now. |
|
477 ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]); |
|
478 } |
|
479 |
|
480 static inline WebDataSource *dataSource(DocumentLoader* loader) |
|
481 { |
|
482 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil; |
|
483 } |
|
484 |
|
485 - (WebDataSource *)_dataSource |
|
486 { |
|
487 return dataSource(_private->coreFrame->loader()->documentLoader()); |
|
488 } |
|
489 |
|
490 - (void)_addData:(NSData *)data |
|
491 { |
|
492 Document* document = _private->coreFrame->document(); |
|
493 |
|
494 // Document may be nil if the part is about to redirect |
|
495 // as a result of JS executing during load, i.e. one frame |
|
496 // changing another's location before the frame's document |
|
497 // has been created. |
|
498 if (!document) |
|
499 return; |
|
500 |
|
501 document->setShouldCreateRenderers(_private->shouldCreateRenderers); |
|
502 _private->coreFrame->loader()->addData((const char *)[data bytes], [data length]); |
|
503 } |
|
504 |
|
505 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString |
|
506 { |
|
507 return _private->coreFrame->documentTypeString() + markupString; |
|
508 } |
|
509 |
|
510 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector |
|
511 { |
|
512 size_t size = nodesVector->size(); |
|
513 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size]; |
|
514 for (size_t i = 0; i < size; ++i) |
|
515 [nodes addObject:kit((*nodesVector)[i])]; |
|
516 return nodes; |
|
517 } |
|
518 |
|
519 - (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes |
|
520 { |
|
521 // FIXME: This is always "for interchange". Is that right? See the previous method. |
|
522 Vector<Node*> nodeList; |
|
523 NSString *markupString = createMarkup(core(range), nodes ? &nodeList : 0, AnnotateForInterchange); |
|
524 if (nodes) |
|
525 *nodes = [self _nodesFromList:&nodeList]; |
|
526 |
|
527 return [self _stringWithDocumentTypeStringAndMarkupString:markupString]; |
|
528 } |
|
529 |
|
530 - (NSString *)_selectedString |
|
531 { |
|
532 return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->selectedText()); |
|
533 } |
|
534 |
|
535 - (NSString *)_stringForRange:(DOMRange *)range |
|
536 { |
|
537 // This will give a system malloc'd buffer that can be turned directly into an NSString |
|
538 unsigned length; |
|
539 UChar* buf = plainTextToMallocAllocatedBuffer(core(range), length, true); |
|
540 |
|
541 if (!buf) |
|
542 return [NSString string]; |
|
543 |
|
544 // Transfer buffer ownership to NSString |
|
545 return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease]; |
|
546 } |
|
547 |
|
548 - (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly |
|
549 { |
|
550 ASSERT([[NSGraphicsContext currentContext] isFlipped]); |
|
551 |
|
552 CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]); |
|
553 GraphicsContext context(ctx); |
|
554 |
|
555 FrameView* view = _private->coreFrame->view(); |
|
556 |
|
557 bool shouldFlatten = false; |
|
558 if (Frame* parentFrame = _private->coreFrame->tree()->parent()) { |
|
559 // For subframes, we need to inherit the paint behavior from our parent |
|
560 FrameView* parentView = parentFrame ? parentFrame->view() : 0; |
|
561 if (parentView) |
|
562 shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers; |
|
563 } else |
|
564 shouldFlatten = WKCGContextIsBitmapContext(ctx) && [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap]; |
|
565 |
|
566 PaintBehavior oldBehavior = PaintBehaviorNormal; |
|
567 if (shouldFlatten) { |
|
568 oldBehavior = view->paintBehavior(); |
|
569 view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers); |
|
570 } |
|
571 |
|
572 if (contentsOnly) |
|
573 _private->coreFrame->view()->paintContents(&context, enclosingIntRect(rect)); |
|
574 else |
|
575 _private->coreFrame->view()->paint(&context, enclosingIntRect(rect)); |
|
576 |
|
577 if (shouldFlatten) |
|
578 view->setPaintBehavior(oldBehavior); |
|
579 } |
|
580 |
|
581 // Used by pagination code called from AppKit when a standalone web page is printed. |
|
582 - (NSArray*)_computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight |
|
583 { |
|
584 NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5]; |
|
585 if (printWidthScaleFactor <= 0) { |
|
586 LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor); |
|
587 return pages; |
|
588 } |
|
589 |
|
590 if (printHeight <= 0) { |
|
591 LOG_ERROR("printHeight has bad value %.2f", printHeight); |
|
592 return pages; |
|
593 } |
|
594 |
|
595 if (!_private->coreFrame || !_private->coreFrame->document() || !_private->coreFrame->view()) return pages; |
|
596 RenderView* root = toRenderView(_private->coreFrame->document()->renderer()); |
|
597 if (!root) return pages; |
|
598 |
|
599 FrameView* view = _private->coreFrame->view(); |
|
600 if (!view) |
|
601 return pages; |
|
602 |
|
603 NSView* documentView = view->documentView(); |
|
604 if (!documentView) |
|
605 return pages; |
|
606 |
|
607 float docWidth = root->layer()->width(); |
|
608 float printWidth = docWidth / printWidthScaleFactor; |
|
609 |
|
610 PrintContext printContext(_private->coreFrame); |
|
611 printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true); |
|
612 |
|
613 const Vector<IntRect>& pageRects = printContext.pageRects(); |
|
614 const size_t pageCount = pageRects.size(); |
|
615 for (size_t pageNumber = 0; pageNumber < pageCount; ++pageNumber) |
|
616 [pages addObject: [NSValue valueWithRect: NSRect(pageRects[pageNumber])]]; |
|
617 return pages; |
|
618 } |
|
619 |
|
620 - (BOOL)_getVisibleRect:(NSRect*)rect |
|
621 { |
|
622 ASSERT_ARG(rect, rect); |
|
623 if (RenderPart* ownerRenderer = _private->coreFrame->ownerRenderer()) { |
|
624 if (ownerRenderer->needsLayout()) |
|
625 return NO; |
|
626 *rect = ownerRenderer->absoluteClippedOverflowRect(); |
|
627 return YES; |
|
628 } |
|
629 |
|
630 return NO; |
|
631 } |
|
632 |
|
633 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string |
|
634 { |
|
635 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true]; |
|
636 } |
|
637 |
|
638 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture |
|
639 { |
|
640 ASSERT(_private->coreFrame->document()); |
|
641 |
|
642 JSValue result = _private->coreFrame->script()->executeScript(string, forceUserGesture).jsValue(); |
|
643 |
|
644 if (!_private->coreFrame) // In case the script removed our frame from the page. |
|
645 return @""; |
|
646 |
|
647 // This bizarre set of rules matches behavior from WebKit for Safari 2.0. |
|
648 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or |
|
649 // JSEvaluateScript instead, since they have less surprising semantics. |
|
650 if (!result || !result.isBoolean() && !result.isString() && !result.isNumber()) |
|
651 return @""; |
|
652 |
|
653 JSLock lock(SilenceAssertionsOnly); |
|
654 return ustringToString(result.toString(_private->coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec())); |
|
655 } |
|
656 |
|
657 - (NSRect)_caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity |
|
658 { |
|
659 VisiblePosition visiblePosition(core(node), offset, static_cast<EAffinity>(affinity)); |
|
660 return visiblePosition.absoluteCaretBounds(); |
|
661 } |
|
662 |
|
663 - (NSRect)_firstRectForDOMRange:(DOMRange *)range |
|
664 { |
|
665 return _private->coreFrame->firstRectForRange(core(range)); |
|
666 } |
|
667 |
|
668 - (void)_scrollDOMRangeToVisible:(DOMRange *)range |
|
669 { |
|
670 NSRect rangeRect = [self _firstRectForDOMRange:range]; |
|
671 Node *startNode = core([range startContainer]); |
|
672 |
|
673 if (startNode && startNode->renderer()) { |
|
674 RenderLayer *layer = startNode->renderer()->enclosingLayer(); |
|
675 if (layer) |
|
676 layer->scrollRectToVisible(enclosingIntRect(rangeRect), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); |
|
677 } |
|
678 } |
|
679 |
|
680 - (BOOL)_needsLayout |
|
681 { |
|
682 return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false; |
|
683 } |
|
684 |
|
685 - (id)_accessibilityTree |
|
686 { |
|
687 #if HAVE(ACCESSIBILITY) |
|
688 if (!AXObjectCache::accessibilityEnabled()) { |
|
689 AXObjectCache::enableAccessibility(); |
|
690 if ([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]) |
|
691 AXObjectCache::enableEnhancedUserInterfaceAccessibility(); |
|
692 } |
|
693 |
|
694 if (!_private->coreFrame || !_private->coreFrame->document()) |
|
695 return nil; |
|
696 RenderView* root = toRenderView(_private->coreFrame->document()->renderer()); |
|
697 if (!root) |
|
698 return nil; |
|
699 return _private->coreFrame->document()->axObjectCache()->getOrCreate(root)->wrapper(); |
|
700 #else |
|
701 return nil; |
|
702 #endif |
|
703 } |
|
704 |
|
705 - (DOMRange *)_rangeByAlteringCurrentSelection:(SelectionController::EAlteration)alteration direction:(SelectionController::EDirection)direction granularity:(TextGranularity)granularity |
|
706 { |
|
707 if (_private->coreFrame->selection()->isNone()) |
|
708 return nil; |
|
709 |
|
710 SelectionController selection; |
|
711 selection.setSelection(_private->coreFrame->selection()->selection()); |
|
712 selection.modify(alteration, direction, granularity); |
|
713 return kit(selection.toNormalizedRange().get()); |
|
714 } |
|
715 |
|
716 - (TextGranularity)_selectionGranularity |
|
717 { |
|
718 return _private->coreFrame->selectionGranularity(); |
|
719 } |
|
720 |
|
721 - (NSRange)_convertToNSRange:(Range *)range |
|
722 { |
|
723 if (!range || !range->startContainer()) |
|
724 return NSMakeRange(NSNotFound, 0); |
|
725 |
|
726 Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement(); |
|
727 Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement(); |
|
728 |
|
729 // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view |
|
730 // that is not inside the current editable region. These checks ensure we don't produce |
|
731 // potentially invalid data when responding to such requests. |
|
732 if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope)) |
|
733 return NSMakeRange(NSNotFound, 0); |
|
734 if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope)) |
|
735 return NSMakeRange(NSNotFound, 0); |
|
736 |
|
737 RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); |
|
738 ASSERT(testRange->startContainer() == scope); |
|
739 int startPosition = TextIterator::rangeLength(testRange.get()); |
|
740 |
|
741 ExceptionCode ec; |
|
742 testRange->setEnd(range->endContainer(), range->endOffset(), ec); |
|
743 ASSERT(testRange->startContainer() == scope); |
|
744 int endPosition = TextIterator::rangeLength(testRange.get()); |
|
745 |
|
746 return NSMakeRange(startPosition, endPosition - startPosition); |
|
747 } |
|
748 |
|
749 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange |
|
750 { |
|
751 if (nsrange.location > INT_MAX) |
|
752 return 0; |
|
753 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX) |
|
754 nsrange.length = INT_MAX - nsrange.location; |
|
755 |
|
756 // our critical assumption is that we are only called by input methods that |
|
757 // concentrate on a given area containing the selection |
|
758 // We have to do this because of text fields and textareas. The DOM for those is not |
|
759 // directly in the document DOM, so serialization is problematic. Our solution is |
|
760 // to use the root editable element of the selection start as the positional base. |
|
761 // That fits with AppKit's idea of an input context. |
|
762 Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement(); |
|
763 Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement(); |
|
764 return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length); |
|
765 } |
|
766 |
|
767 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange |
|
768 { |
|
769 // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160> |
|
770 return [self _convertNSRangeToDOMRange:nsrange]; |
|
771 } |
|
772 |
|
773 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange |
|
774 { |
|
775 return kit([self _convertToDOMRange:nsrange].get()); |
|
776 } |
|
777 |
|
778 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range |
|
779 { |
|
780 // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160> |
|
781 return [self _convertDOMRangeToNSRange:range]; |
|
782 } |
|
783 |
|
784 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range |
|
785 { |
|
786 return [self _convertToNSRange:core(range)]; |
|
787 } |
|
788 |
|
789 - (DOMRange *)_markDOMRange |
|
790 { |
|
791 return kit(_private->coreFrame->mark().toNormalizedRange().get()); |
|
792 } |
|
793 |
|
794 // Given proposedRange, returns an extended range that includes adjacent whitespace that should |
|
795 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of |
|
796 // the text surrounding the deletion. |
|
797 - (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange |
|
798 { |
|
799 Node* startContainer = core([proposedRange startContainer]); |
|
800 Node* endContainer = core([proposedRange endContainer]); |
|
801 if (startContainer == nil || endContainer == nil) |
|
802 return nil; |
|
803 |
|
804 ASSERT(startContainer->document() == endContainer->document()); |
|
805 |
|
806 _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets(); |
|
807 |
|
808 Position start(startContainer, [proposedRange startOffset]); |
|
809 Position end(endContainer, [proposedRange endOffset]); |
|
810 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true); |
|
811 if (newStart.isNull()) |
|
812 newStart = start; |
|
813 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true); |
|
814 if (newEnd.isNull()) |
|
815 newEnd = end; |
|
816 |
|
817 newStart = rangeCompliantEquivalent(newStart); |
|
818 newEnd = rangeCompliantEquivalent(newEnd); |
|
819 |
|
820 RefPtr<Range> range = _private->coreFrame->document()->createRange(); |
|
821 int exception = 0; |
|
822 range->setStart(newStart.node(), newStart.deprecatedEditingOffset(), exception); |
|
823 range->setEnd(newStart.node(), newStart.deprecatedEditingOffset(), exception); |
|
824 return kit(range.get()); |
|
825 } |
|
826 |
|
827 // Determines whether whitespace needs to be added around aString to preserve proper spacing and |
|
828 // punctuation when it’s inserted into the receiver’s text over charRange. Returns by reference |
|
829 // in beforeString and afterString any whitespace that should be added, unless either or both are |
|
830 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled. |
|
831 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString |
|
832 { |
|
833 // give back nil pointers in case of early returns |
|
834 if (beforeString) |
|
835 *beforeString = nil; |
|
836 if (afterString) |
|
837 *afterString = nil; |
|
838 |
|
839 // inspect destination |
|
840 Node *startContainer = core([rangeToReplace startContainer]); |
|
841 Node *endContainer = core([rangeToReplace endContainer]); |
|
842 |
|
843 Position startPos(startContainer, [rangeToReplace startOffset]); |
|
844 Position endPos(endContainer, [rangeToReplace endOffset]); |
|
845 |
|
846 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY); |
|
847 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY); |
|
848 |
|
849 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null |
|
850 if (startVisiblePos.isNull() || endVisiblePos.isNull()) |
|
851 return; |
|
852 |
|
853 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos); |
|
854 if (addLeadingSpace) |
|
855 if (UChar previousChar = startVisiblePos.previous().characterAfter()) |
|
856 addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true); |
|
857 |
|
858 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos); |
|
859 if (addTrailingSpace) |
|
860 if (UChar thisChar = endVisiblePos.characterAfter()) |
|
861 addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false); |
|
862 |
|
863 // inspect source |
|
864 bool hasWhitespaceAtStart = false; |
|
865 bool hasWhitespaceAtEnd = false; |
|
866 unsigned pasteLength = [pasteString length]; |
|
867 if (pasteLength > 0) { |
|
868 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; |
|
869 |
|
870 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) { |
|
871 hasWhitespaceAtStart = YES; |
|
872 } |
|
873 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) { |
|
874 hasWhitespaceAtEnd = YES; |
|
875 } |
|
876 } |
|
877 |
|
878 // issue the verdict |
|
879 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart) |
|
880 *beforeString = @" "; |
|
881 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd) |
|
882 *afterString = @" "; |
|
883 } |
|
884 |
|
885 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString |
|
886 { |
|
887 if (!_private->coreFrame || !_private->coreFrame->document()) |
|
888 return nil; |
|
889 |
|
890 return kit(createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString, FragmentScriptingNotAllowed).get()); |
|
891 } |
|
892 |
|
893 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes |
|
894 { |
|
895 if (!_private->coreFrame || !_private->coreFrame->document()) |
|
896 return nil; |
|
897 |
|
898 NSEnumerator *nodeEnum = [nodes objectEnumerator]; |
|
899 Vector<Node*> nodesVector; |
|
900 DOMNode *node; |
|
901 while ((node = [nodeEnum nextObject])) |
|
902 nodesVector.append(core(node)); |
|
903 |
|
904 return kit(createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get()); |
|
905 } |
|
906 |
|
907 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle |
|
908 { |
|
909 DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().get()); |
|
910 [fragment appendChild:node]; |
|
911 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle]; |
|
912 } |
|
913 |
|
914 - (void)_insertParagraphSeparatorInQuotedContent |
|
915 { |
|
916 if (_private->coreFrame->selection()->isNone()) |
|
917 return; |
|
918 |
|
919 TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document()); |
|
920 _private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded); |
|
921 } |
|
922 |
|
923 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point |
|
924 { |
|
925 // FIXME: Someone with access to Apple's sources could remove this needless wrapper call. |
|
926 return _private->coreFrame->visiblePositionForPoint(IntPoint(point)); |
|
927 } |
|
928 |
|
929 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point |
|
930 { |
|
931 VisiblePosition position = [self _visiblePositionForPoint:point]; |
|
932 if (position.isNull()) |
|
933 return nil; |
|
934 |
|
935 VisiblePosition previous = position.previous(); |
|
936 if (previous.isNotNull()) { |
|
937 DOMRange *previousCharacterRange = kit(makeRange(previous, position).get()); |
|
938 NSRect rect = [self _firstRectForDOMRange:previousCharacterRange]; |
|
939 if (NSPointInRect(point, rect)) |
|
940 return previousCharacterRange; |
|
941 } |
|
942 |
|
943 VisiblePosition next = position.next(); |
|
944 if (next.isNotNull()) { |
|
945 DOMRange *nextCharacterRange = kit(makeRange(position, next).get()); |
|
946 NSRect rect = [self _firstRectForDOMRange:nextCharacterRange]; |
|
947 if (NSPointInRect(point, rect)) |
|
948 return nextCharacterRange; |
|
949 } |
|
950 |
|
951 return nil; |
|
952 } |
|
953 |
|
954 - (DOMCSSStyleDeclaration *)_typingStyle |
|
955 { |
|
956 if (!_private->coreFrame || !_private->coreFrame->typingStyle()) |
|
957 return nil; |
|
958 return kit(_private->coreFrame->typingStyle()->copy().get()); |
|
959 } |
|
960 |
|
961 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction |
|
962 { |
|
963 if (!_private->coreFrame) |
|
964 return; |
|
965 _private->coreFrame->computeAndSetTypingStyle(core(style), undoAction); |
|
966 } |
|
967 |
|
968 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation |
|
969 { |
|
970 if (!_private->coreFrame) |
|
971 return; |
|
972 FrameView* view = _private->coreFrame->view(); |
|
973 if (!view) |
|
974 return; |
|
975 ASSERT([getWebView(self) _usesDocumentViews]); |
|
976 // FIXME: These are fake modifier keys here, but they should be real ones instead. |
|
977 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), |
|
978 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); |
|
979 _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation); |
|
980 } |
|
981 |
|
982 - (BOOL)_canProvideDocumentSource |
|
983 { |
|
984 Frame* frame = _private->coreFrame; |
|
985 String mimeType = frame->loader()->writer()->mimeType(); |
|
986 PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0; |
|
987 |
|
988 if (WebCore::DOMImplementation::isTextMIMEType(mimeType) || |
|
989 Image::supportsType(mimeType) || |
|
990 (pluginData && pluginData->supportsMimeType(mimeType))) |
|
991 return NO; |
|
992 |
|
993 return YES; |
|
994 } |
|
995 |
|
996 - (BOOL)_canSaveAsWebArchive |
|
997 { |
|
998 // Currently, all documents that we can view source for |
|
999 // (HTML and XML documents) can also be saved as web archives |
|
1000 return [self _canProvideDocumentSource]; |
|
1001 } |
|
1002 |
|
1003 - (void)_receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName |
|
1004 { |
|
1005 // Set the encoding. This only needs to be done once, but it's harmless to do it again later. |
|
1006 String encoding = _private->coreFrame->loader()->documentLoader()->overrideEncoding(); |
|
1007 bool userChosen = !encoding.isNull(); |
|
1008 if (encoding.isNull()) |
|
1009 encoding = textEncodingName; |
|
1010 _private->coreFrame->loader()->writer()->setEncoding(encoding, userChosen); |
|
1011 [self _addData:data]; |
|
1012 } |
|
1013 |
|
1014 @end |
|
1015 |
|
1016 @implementation WebFrame (WebPrivate) |
|
1017 |
|
1018 // FIXME: This exists only as a convenience for Safari, consider moving there. |
|
1019 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor |
|
1020 { |
|
1021 Frame* coreFrame = _private->coreFrame; |
|
1022 return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor)); |
|
1023 } |
|
1024 |
|
1025 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers |
|
1026 { |
|
1027 _private->shouldCreateRenderers = shouldCreateRenderers; |
|
1028 } |
|
1029 |
|
1030 - (NSColor *)_bodyBackgroundColor |
|
1031 { |
|
1032 Document* document = _private->coreFrame->document(); |
|
1033 if (!document) |
|
1034 return nil; |
|
1035 HTMLElement* body = document->body(); |
|
1036 if (!body) |
|
1037 return nil; |
|
1038 RenderObject* bodyRenderer = body->renderer(); |
|
1039 if (!bodyRenderer) |
|
1040 return nil; |
|
1041 Color color = bodyRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor); |
|
1042 if (!color.isValid()) |
|
1043 return nil; |
|
1044 return nsColor(color); |
|
1045 } |
|
1046 |
|
1047 - (BOOL)_isFrameSet |
|
1048 { |
|
1049 Document* document = _private->coreFrame->document(); |
|
1050 return document && document->isFrameSet(); |
|
1051 } |
|
1052 |
|
1053 - (BOOL)_firstLayoutDone |
|
1054 { |
|
1055 return _private->coreFrame->loader()->stateMachine()->firstLayoutDone(); |
|
1056 } |
|
1057 |
|
1058 - (WebFrameLoadType)_loadType |
|
1059 { |
|
1060 return (WebFrameLoadType)_private->coreFrame->loader()->loadType(); |
|
1061 } |
|
1062 |
|
1063 - (NSRange)_selectedNSRange |
|
1064 { |
|
1065 return [self _convertToNSRange:_private->coreFrame->selection()->toNormalizedRange().get()]; |
|
1066 } |
|
1067 |
|
1068 - (void)_selectNSRange:(NSRange)range |
|
1069 { |
|
1070 RefPtr<Range> domRange = [self _convertToDOMRange:range]; |
|
1071 if (domRange) |
|
1072 _private->coreFrame->selection()->setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY)); |
|
1073 } |
|
1074 |
|
1075 - (BOOL)_isDisplayingStandaloneImage |
|
1076 { |
|
1077 Document* document = _private->coreFrame->document(); |
|
1078 return document && document->isImageDocument(); |
|
1079 } |
|
1080 |
|
1081 - (unsigned)_pendingFrameUnloadEventCount |
|
1082 { |
|
1083 return _private->coreFrame->domWindow()->pendingUnloadEventListeners(); |
|
1084 } |
|
1085 |
|
1086 - (WebIconFetcher *)fetchApplicationIcon:(id)target |
|
1087 selector:(SEL)selector |
|
1088 { |
|
1089 return [WebIconFetcher _fetchApplicationIconForFrame:self |
|
1090 target:target |
|
1091 selector:selector]; |
|
1092 } |
|
1093 |
|
1094 - (void)_setIsDisconnected:(bool)isDisconnected |
|
1095 { |
|
1096 _private->coreFrame->setIsDisconnected(isDisconnected); |
|
1097 } |
|
1098 |
|
1099 - (void)_setExcludeFromTextSearch:(bool)exclude |
|
1100 { |
|
1101 _private->coreFrame->setExcludeFromTextSearch(exclude); |
|
1102 } |
|
1103 |
|
1104 #if ENABLE(NETSCAPE_PLUGIN_API) |
|
1105 - (void)_recursive_resumeNullEventsForAllNetscapePlugins |
|
1106 { |
|
1107 Frame* coreFrame = core(self); |
|
1108 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { |
|
1109 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; |
|
1110 if ([documentView isKindOfClass:[WebHTMLView class]]) |
|
1111 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins]; |
|
1112 } |
|
1113 } |
|
1114 |
|
1115 - (void)_recursive_pauseNullEventsForAllNetscapePlugins |
|
1116 { |
|
1117 Frame* coreFrame = core(self); |
|
1118 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) { |
|
1119 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView]; |
|
1120 if ([documentView isKindOfClass:[WebHTMLView class]]) |
|
1121 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins]; |
|
1122 } |
|
1123 } |
|
1124 #endif |
|
1125 |
|
1126 - (BOOL)_pauseAnimation:(NSString*)name onNode:(DOMNode *)node atTime:(NSTimeInterval)time |
|
1127 { |
|
1128 Frame* frame = core(self); |
|
1129 if (!frame) |
|
1130 return false; |
|
1131 |
|
1132 AnimationController* controller = frame->animation(); |
|
1133 if (!controller) |
|
1134 return false; |
|
1135 |
|
1136 Node* coreNode = core(node); |
|
1137 if (!coreNode || !coreNode->renderer()) |
|
1138 return false; |
|
1139 |
|
1140 return controller->pauseAnimationAtTime(coreNode->renderer(), name, time); |
|
1141 } |
|
1142 |
|
1143 - (BOOL)_pauseTransitionOfProperty:(NSString*)name onNode:(DOMNode*)node atTime:(NSTimeInterval)time |
|
1144 { |
|
1145 Frame* frame = core(self); |
|
1146 if (!frame) |
|
1147 return false; |
|
1148 |
|
1149 AnimationController* controller = frame->animation(); |
|
1150 if (!controller) |
|
1151 return false; |
|
1152 |
|
1153 Node* coreNode = core(node); |
|
1154 if (!coreNode || !coreNode->renderer()) |
|
1155 return false; |
|
1156 |
|
1157 return controller->pauseTransitionAtTime(coreNode->renderer(), name, time); |
|
1158 } |
|
1159 |
|
1160 // Pause a given SVG animation on the target node at a specific time. |
|
1161 // This method is only intended to be used for testing the SVG animation system. |
|
1162 - (BOOL)_pauseSVGAnimation:(NSString*)elementId onSMILNode:(DOMNode *)node atTime:(NSTimeInterval)time |
|
1163 { |
|
1164 Frame* frame = core(self); |
|
1165 if (!frame) |
|
1166 return false; |
|
1167 |
|
1168 Document* document = frame->document(); |
|
1169 if (!document || !document->svgExtensions()) |
|
1170 return false; |
|
1171 |
|
1172 Node* coreNode = core(node); |
|
1173 if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) |
|
1174 return false; |
|
1175 |
|
1176 #if ENABLE(SVG) |
|
1177 return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time); |
|
1178 #else |
|
1179 return false; |
|
1180 #endif |
|
1181 } |
|
1182 |
|
1183 - (unsigned) _numberOfActiveAnimations |
|
1184 { |
|
1185 Frame* frame = core(self); |
|
1186 if (!frame) |
|
1187 return false; |
|
1188 |
|
1189 AnimationController* controller = frame->animation(); |
|
1190 if (!controller) |
|
1191 return false; |
|
1192 |
|
1193 return controller->numberOfActiveAnimations(); |
|
1194 } |
|
1195 |
|
1196 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle |
|
1197 { |
|
1198 if (_private->coreFrame->selection()->isNone() || !fragment) |
|
1199 return; |
|
1200 |
|
1201 applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), core(fragment), selectReplacement, smartReplace, matchStyle)); |
|
1202 _private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded); |
|
1203 } |
|
1204 |
|
1205 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace |
|
1206 { |
|
1207 DOMDocumentFragment* fragment = kit(createFragmentFromText(_private->coreFrame->selection()->toNormalizedRange().get(), text).get()); |
|
1208 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES]; |
|
1209 } |
|
1210 |
|
1211 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace |
|
1212 { |
|
1213 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString]; |
|
1214 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO]; |
|
1215 } |
|
1216 |
|
1217 - (NSMutableDictionary *)_cacheabilityDictionary |
|
1218 { |
|
1219 NSMutableDictionary *result = [NSMutableDictionary dictionary]; |
|
1220 |
|
1221 FrameLoader* frameLoader = _private->coreFrame->loader(); |
|
1222 DocumentLoader* documentLoader = frameLoader->documentLoader(); |
|
1223 if (documentLoader && !documentLoader->mainDocumentError().isNull()) |
|
1224 [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError]; |
|
1225 |
|
1226 if (frameLoader->subframeLoader()->containsPlugins()) |
|
1227 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins]; |
|
1228 |
|
1229 if (DOMWindow* domWindow = _private->coreFrame->domWindow()) { |
|
1230 if (domWindow->hasEventListeners(eventNames().unloadEvent)) |
|
1231 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener]; |
|
1232 |
|
1233 #if ENABLE(OFFLINE_WEB_APPLICATIONS) |
|
1234 if (domWindow->optionalApplicationCache()) |
|
1235 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache]; |
|
1236 #endif |
|
1237 } |
|
1238 |
|
1239 if (Document* document = _private->coreFrame->document()) { |
|
1240 #if ENABLE(DATABASE) |
|
1241 if (document->hasOpenDatabases()) |
|
1242 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases]; |
|
1243 #endif |
|
1244 |
|
1245 if (document->usingGeolocation()) |
|
1246 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesGeolocation]; |
|
1247 |
|
1248 if (!document->canSuspendActiveDOMObjects()) |
|
1249 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects]; |
|
1250 } |
|
1251 |
|
1252 return result; |
|
1253 } |
|
1254 |
|
1255 - (BOOL)_allowsFollowingLink:(NSURL *)URL |
|
1256 { |
|
1257 if (!_private->coreFrame) |
|
1258 return YES; |
|
1259 return SecurityOrigin::canLoad(URL, String(), _private->coreFrame->document()); |
|
1260 } |
|
1261 |
|
1262 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world |
|
1263 { |
|
1264 // Start off with some guess at a frame and a global object, we'll try to do better...! |
|
1265 JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script()->globalObject(mainThreadNormalWorld()); |
|
1266 |
|
1267 // The global object is probably a shell object? - if so, we know how to use this! |
|
1268 JSC::JSObject* globalObjectObj = toJS(globalObjectRef); |
|
1269 if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell")) |
|
1270 anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window(); |
|
1271 |
|
1272 // Get the frame frome the global object we've settled on. |
|
1273 Frame* frame = anyWorldGlobalObject->impl()->frame(); |
|
1274 ASSERT(frame->document()); |
|
1275 JSValue result = frame->script()->executeScriptInWorld(core(world), string, true).jsValue(); |
|
1276 |
|
1277 if (!frame) // In case the script removed our frame from the page. |
|
1278 return @""; |
|
1279 |
|
1280 // This bizarre set of rules matches behavior from WebKit for Safari 2.0. |
|
1281 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or |
|
1282 // JSEvaluateScript instead, since they have less surprising semantics. |
|
1283 if (!result || !result.isBoolean() && !result.isString() && !result.isNumber()) |
|
1284 return @""; |
|
1285 |
|
1286 JSLock lock(SilenceAssertionsOnly); |
|
1287 return ustringToString(result.toString(anyWorldGlobalObject->globalExec())); |
|
1288 } |
|
1289 |
|
1290 - (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world |
|
1291 { |
|
1292 Frame* coreFrame = _private->coreFrame; |
|
1293 if (!coreFrame) |
|
1294 return 0; |
|
1295 DOMWrapperWorld* coreWorld = core(world); |
|
1296 if (!coreWorld) |
|
1297 return 0; |
|
1298 return toGlobalRef(coreFrame->script()->globalObject(coreWorld)->globalExec()); |
|
1299 } |
|
1300 |
|
1301 - (void)setAllowsScrollersToOverlapContent:(BOOL)flag |
|
1302 { |
|
1303 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]); |
|
1304 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag]; |
|
1305 } |
|
1306 |
|
1307 - (void)setAlwaysHideHorizontalScroller:(BOOL)flag |
|
1308 { |
|
1309 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]); |
|
1310 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag]; |
|
1311 } |
|
1312 - (void)setAlwaysHideVerticalScroller:(BOOL)flag |
|
1313 { |
|
1314 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]); |
|
1315 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag]; |
|
1316 } |
|
1317 |
|
1318 - (void)setAccessibleName:(NSString *)name |
|
1319 { |
|
1320 #if HAVE(ACCESSIBILITY) |
|
1321 if (!AXObjectCache::accessibilityEnabled()) |
|
1322 return; |
|
1323 |
|
1324 RenderView* root = toRenderView(_private->coreFrame->document()->renderer()); |
|
1325 if (!root) |
|
1326 return; |
|
1327 |
|
1328 AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->getOrCreate(root); |
|
1329 String strName(name); |
|
1330 rootObject->setAccessibleName(strName); |
|
1331 #endif |
|
1332 } |
|
1333 |
|
1334 - (NSString*)_layerTreeAsText |
|
1335 { |
|
1336 Frame* coreFrame = _private->coreFrame; |
|
1337 if (!coreFrame) |
|
1338 return @""; |
|
1339 |
|
1340 return coreFrame->layerTreeAsText(); |
|
1341 } |
|
1342 |
|
1343 @end |
|
1344 |
|
1345 @implementation WebFrame |
|
1346 |
|
1347 - (id)init |
|
1348 { |
|
1349 return nil; |
|
1350 } |
|
1351 |
|
1352 // Should be deprecated. |
|
1353 - (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView |
|
1354 { |
|
1355 return nil; |
|
1356 } |
|
1357 |
|
1358 - (void)dealloc |
|
1359 { |
|
1360 if (_private && _private->includedInWebKitStatistics) |
|
1361 --WebFrameCount; |
|
1362 |
|
1363 [_private release]; |
|
1364 |
|
1365 [super dealloc]; |
|
1366 } |
|
1367 |
|
1368 - (void)finalize |
|
1369 { |
|
1370 if (_private && _private->includedInWebKitStatistics) |
|
1371 --WebFrameCount; |
|
1372 |
|
1373 [super finalize]; |
|
1374 } |
|
1375 |
|
1376 - (NSString *)name |
|
1377 { |
|
1378 Frame* coreFrame = _private->coreFrame; |
|
1379 if (!coreFrame) |
|
1380 return nil; |
|
1381 return coreFrame->tree()->name(); |
|
1382 } |
|
1383 |
|
1384 - (WebFrameView *)frameView |
|
1385 { |
|
1386 ASSERT(!getWebView(self) || [getWebView(self) _usesDocumentViews]); |
|
1387 return _private->webFrameView; |
|
1388 } |
|
1389 |
|
1390 - (WebView *)webView |
|
1391 { |
|
1392 return getWebView(self); |
|
1393 } |
|
1394 |
|
1395 static bool needsMicrosoftMessengerDOMDocumentWorkaround() |
|
1396 { |
|
1397 static bool needsWorkaround = applicationIsMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending; |
|
1398 return needsWorkaround; |
|
1399 } |
|
1400 |
|
1401 - (DOMDocument *)DOMDocument |
|
1402 { |
|
1403 if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np()) |
|
1404 return nil; |
|
1405 |
|
1406 Frame* coreFrame = _private->coreFrame; |
|
1407 if (!coreFrame) |
|
1408 return nil; |
|
1409 |
|
1410 // FIXME: <rdar://problem/5145841> When loading a custom view/representation |
|
1411 // into a web frame, the old document can still be around. This makes sure that |
|
1412 // we'll return nil in those cases. |
|
1413 if (![[self _dataSource] _isDocumentHTML]) |
|
1414 return nil; |
|
1415 |
|
1416 Document* document = coreFrame->document(); |
|
1417 |
|
1418 // According to the documentation, we should return nil if the frame doesn't have a document. |
|
1419 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be |
|
1420 // backwards compatible. |
|
1421 if (document && (document->isPluginDocument() || document->isImageDocument())) |
|
1422 return nil; |
|
1423 |
|
1424 return kit(coreFrame->document()); |
|
1425 } |
|
1426 |
|
1427 - (DOMHTMLElement *)frameElement |
|
1428 { |
|
1429 Frame* coreFrame = _private->coreFrame; |
|
1430 if (!coreFrame) |
|
1431 return nil; |
|
1432 return kit(coreFrame->ownerElement()); |
|
1433 } |
|
1434 |
|
1435 - (WebDataSource *)provisionalDataSource |
|
1436 { |
|
1437 Frame* coreFrame = _private->coreFrame; |
|
1438 return coreFrame ? dataSource(coreFrame->loader()->provisionalDocumentLoader()) : nil; |
|
1439 } |
|
1440 |
|
1441 - (WebDataSource *)dataSource |
|
1442 { |
|
1443 Frame* coreFrame = _private->coreFrame; |
|
1444 return coreFrame && coreFrame->loader()->frameHasLoaded() ? [self _dataSource] : nil; |
|
1445 } |
|
1446 |
|
1447 - (void)loadRequest:(NSURLRequest *)request |
|
1448 { |
|
1449 Frame* coreFrame = _private->coreFrame; |
|
1450 if (!coreFrame) |
|
1451 return; |
|
1452 coreFrame->loader()->load(request, false); |
|
1453 } |
|
1454 |
|
1455 static NSURL *createUniqueWebDataURL() |
|
1456 { |
|
1457 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault); |
|
1458 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef); |
|
1459 CFRelease(UUIDRef); |
|
1460 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]]; |
|
1461 CFRelease(UUIDString); |
|
1462 return URL; |
|
1463 } |
|
1464 |
|
1465 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL |
|
1466 { |
|
1467 if (!pthread_main_np()) |
|
1468 return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL]; |
|
1469 |
|
1470 KURL responseURL; |
|
1471 if (!baseURL) { |
|
1472 baseURL = blankURL(); |
|
1473 responseURL = createUniqueWebDataURL(); |
|
1474 } |
|
1475 |
|
1476 ResourceRequest request([baseURL absoluteURL]); |
|
1477 |
|
1478 // hack because Mail checks for this property to detect data / archive loads |
|
1479 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()]; |
|
1480 |
|
1481 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL); |
|
1482 |
|
1483 _private->coreFrame->loader()->load(request, substituteData, false); |
|
1484 } |
|
1485 |
|
1486 |
|
1487 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL |
|
1488 { |
|
1489 WebCoreThreadViolationCheckRoundTwo(); |
|
1490 |
|
1491 if (!MIMEType) |
|
1492 MIMEType = @"text/html"; |
|
1493 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil]; |
|
1494 } |
|
1495 |
|
1496 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL |
|
1497 { |
|
1498 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; |
|
1499 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL]; |
|
1500 } |
|
1501 |
|
1502 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL |
|
1503 { |
|
1504 WebCoreThreadViolationCheckRoundTwo(); |
|
1505 |
|
1506 [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil]; |
|
1507 } |
|
1508 |
|
1509 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL |
|
1510 { |
|
1511 WebCoreThreadViolationCheckRoundTwo(); |
|
1512 |
|
1513 [self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL]; |
|
1514 } |
|
1515 |
|
1516 - (void)loadArchive:(WebArchive *)archive |
|
1517 { |
|
1518 if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive]) |
|
1519 _private->coreFrame->loader()->loadArchive(coreArchive); |
|
1520 } |
|
1521 |
|
1522 - (void)stopLoading |
|
1523 { |
|
1524 if (!_private->coreFrame) |
|
1525 return; |
|
1526 _private->coreFrame->loader()->stopForUserCancel(); |
|
1527 } |
|
1528 |
|
1529 - (void)reload |
|
1530 { |
|
1531 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && applicationIsSafari()) |
|
1532 _private->coreFrame->loader()->reload(GetCurrentKeyModifiers() & shiftKey); |
|
1533 else |
|
1534 _private->coreFrame->loader()->reload(false); |
|
1535 } |
|
1536 |
|
1537 - (void)reloadFromOrigin |
|
1538 { |
|
1539 _private->coreFrame->loader()->reload(true); |
|
1540 } |
|
1541 |
|
1542 - (WebFrame *)findFrameNamed:(NSString *)name |
|
1543 { |
|
1544 Frame* coreFrame = _private->coreFrame; |
|
1545 if (!coreFrame) |
|
1546 return nil; |
|
1547 return kit(coreFrame->tree()->find(name)); |
|
1548 } |
|
1549 |
|
1550 - (WebFrame *)parentFrame |
|
1551 { |
|
1552 Frame* coreFrame = _private->coreFrame; |
|
1553 if (!coreFrame) |
|
1554 return nil; |
|
1555 return [[kit(coreFrame->tree()->parent()) retain] autorelease]; |
|
1556 } |
|
1557 |
|
1558 - (NSArray *)childFrames |
|
1559 { |
|
1560 Frame* coreFrame = _private->coreFrame; |
|
1561 if (!coreFrame) |
|
1562 return [NSArray array]; |
|
1563 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()]; |
|
1564 for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) |
|
1565 [children addObject:kit(child)]; |
|
1566 return children; |
|
1567 } |
|
1568 |
|
1569 - (WebScriptObject *)windowObject |
|
1570 { |
|
1571 Frame* coreFrame = _private->coreFrame; |
|
1572 if (!coreFrame) |
|
1573 return 0; |
|
1574 return coreFrame->script()->windowScriptObject(); |
|
1575 } |
|
1576 |
|
1577 - (JSGlobalContextRef)globalContext |
|
1578 { |
|
1579 Frame* coreFrame = _private->coreFrame; |
|
1580 if (!coreFrame) |
|
1581 return 0; |
|
1582 return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()); |
|
1583 } |
|
1584 |
|
1585 @end |