|
1 /* |
|
2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. |
|
3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com) |
|
4 * |
|
5 * Redistribution and use in source and binary forms, with or without |
|
6 * modification, are permitted provided that the following conditions |
|
7 * are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * 2. Redistributions in binary form must reproduce the above copyright |
|
12 * notice, this list of conditions and the following disclaimer in the |
|
13 * documentation and/or other materials provided with the distribution. |
|
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
|
15 * its contributors may be used to endorse or promote products derived |
|
16 * from this software without specific prior written permission. |
|
17 * |
|
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
|
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 */ |
|
29 |
|
30 #import "WebViewInternal.h" |
|
31 |
|
32 #import "DOMRangeInternal.h" |
|
33 #import "WebBackForwardList.h" |
|
34 #import "WebBackForwardListInternal.h" |
|
35 #import "WebBaseNetscapePluginView.h" |
|
36 #import "WebChromeClient.h" |
|
37 #import "WebContextMenuClient.h" |
|
38 #import "WebDOMOperationsPrivate.h" |
|
39 #import "WebDashboardRegion.h" |
|
40 #import "WebDataSourceInternal.h" |
|
41 #import "WebDefaultEditingDelegate.h" |
|
42 #import "WebDefaultPolicyDelegate.h" |
|
43 #import "WebDefaultScriptDebugDelegate.h" |
|
44 #import "WebDefaultUIDelegate.h" |
|
45 #import "WebDocument.h" |
|
46 #import "WebDocumentInternal.h" |
|
47 #import "WebDownload.h" |
|
48 #import "WebDownloadInternal.h" |
|
49 #import "WebDragClient.h" |
|
50 #import "WebDynamicScrollBarsView.h" |
|
51 #import "WebEditingDelegate.h" |
|
52 #import "WebEditorClient.h" |
|
53 #import "WebFormDelegatePrivate.h" |
|
54 #import "WebFrameBridge.h" |
|
55 #import "WebFrameInternal.h" |
|
56 #import "WebFrameViewInternal.h" |
|
57 #import "WebHTMLRepresentation.h" |
|
58 #import "WebHTMLViewInternal.h" |
|
59 #import "WebHistoryItemInternal.h" |
|
60 #import "WebIconDatabase.h" |
|
61 #import "WebIconDatabaseInternal.h" |
|
62 #import "WebInspectorClient.h" |
|
63 #import "WebKitErrors.h" |
|
64 #import "WebKitLogging.h" |
|
65 #import "WebKitNSStringExtras.h" |
|
66 #import "WebKitStatisticsPrivate.h" |
|
67 #import "WebKitSystemBits.h" |
|
68 #import "WebKitVersionChecks.h" |
|
69 #import "WebLocalizableStrings.h" |
|
70 #import "WebNSDataExtras.h" |
|
71 #import "WebNSDataExtrasPrivate.h" |
|
72 #import "WebNSDictionaryExtras.h" |
|
73 #import "WebNSEventExtras.h" |
|
74 #import "WebNSObjectExtras.h" |
|
75 #import "WebNSPasteboardExtras.h" |
|
76 #import "WebNSPrintOperationExtras.h" |
|
77 #import "WebNSURLExtras.h" |
|
78 #import "WebNSURLRequestExtras.h" |
|
79 #import "WebNSUserDefaultsExtras.h" |
|
80 #import "WebNSViewExtras.h" |
|
81 #import "WebPanelAuthenticationHandler.h" |
|
82 #import "WebPasteboardHelper.h" |
|
83 #import "WebPDFView.h" |
|
84 #import "WebPluginDatabase.h" |
|
85 #import "WebPolicyDelegate.h" |
|
86 #import "WebPreferenceKeysPrivate.h" |
|
87 #import "WebPreferencesPrivate.h" |
|
88 #import "WebScriptDebugDelegatePrivate.h" |
|
89 #import "WebScriptDebugServerPrivate.h" |
|
90 #import "WebUIDelegate.h" |
|
91 #import "WebUIDelegatePrivate.h" |
|
92 #import <CoreFoundation/CFSet.h> |
|
93 #import <Foundation/NSURLConnection.h> |
|
94 #import <JavaScriptCore/Assertions.h> |
|
95 #import <WebCore/Cache.h> |
|
96 #import <WebCore/ColorMac.h> |
|
97 #import <WebCore/Document.h> |
|
98 #import <WebCore/DocumentLoader.h> |
|
99 #import <WebCore/DragController.h> |
|
100 #import <WebCore/DragData.h> |
|
101 #import <WebCore/Editor.h> |
|
102 #import <WebCore/ExceptionHandlers.h> |
|
103 #import <WebCore/Frame.h> |
|
104 #import <WebCore/FrameLoader.h> |
|
105 #import <WebCore/FrameTree.h> |
|
106 #import <WebCore/HTMLNames.h> |
|
107 #import <WebCore/HistoryItem.h> |
|
108 #import <WebCore/Logging.h> |
|
109 #import <WebCore/MIMETypeRegistry.h> |
|
110 #import <WebCore/Page.h> |
|
111 #import <WebCore/PageCache.h> |
|
112 #import <WebCore/PlatformMouseEvent.h> |
|
113 #import <WebCore/ProgressTracker.h> |
|
114 #import <WebCore/SelectionController.h> |
|
115 #import <WebCore/Settings.h> |
|
116 #import <WebCore/TextResourceDecoder.h> |
|
117 #import <WebCore/WebCoreFrameBridge.h> |
|
118 #import <WebCore/WebCoreObjCExtras.h> |
|
119 #import <WebCore/WebCoreTextRenderer.h> |
|
120 #import <WebCore/WebCoreView.h> |
|
121 #import <WebKit/DOM.h> |
|
122 #import <WebKit/DOMExtensions.h> |
|
123 #import <WebKit/DOMPrivate.h> |
|
124 #import <WebKitSystemInterface.h> |
|
125 #import <mach-o/dyld.h> |
|
126 #import <objc/objc-runtime.h> |
|
127 #import <wtf/RefPtr.h> |
|
128 #import <wtf/HashTraits.h> |
|
129 |
|
130 using namespace WebCore; |
|
131 |
|
132 #if defined(__ppc__) || defined(__ppc64__) |
|
133 #define PROCESSOR "PPC" |
|
134 #elif defined(__i386__) || defined(__x86_64__) |
|
135 #define PROCESSOR "Intel" |
|
136 #else |
|
137 #error Unknown architecture |
|
138 #endif |
|
139 |
|
140 #define FOR_EACH_RESPONDER_SELECTOR(macro) \ |
|
141 macro(alignCenter) \ |
|
142 macro(alignJustified) \ |
|
143 macro(alignLeft) \ |
|
144 macro(alignRight) \ |
|
145 macro(capitalizeWord) \ |
|
146 macro(centerSelectionInVisibleArea) \ |
|
147 macro(changeAttributes) \ |
|
148 macro(changeColor) \ |
|
149 macro(changeDocumentBackgroundColor) \ |
|
150 macro(changeFont) \ |
|
151 macro(checkSpelling) \ |
|
152 macro(complete) \ |
|
153 macro(copy) \ |
|
154 macro(copyFont) \ |
|
155 macro(cut) \ |
|
156 macro(delete) \ |
|
157 macro(deleteBackward) \ |
|
158 macro(deleteBackwardByDecomposingPreviousCharacter) \ |
|
159 macro(deleteForward) \ |
|
160 macro(deleteToBeginningOfLine) \ |
|
161 macro(deleteToBeginningOfParagraph) \ |
|
162 macro(deleteToEndOfLine) \ |
|
163 macro(deleteToEndOfParagraph) \ |
|
164 macro(deleteWordBackward) \ |
|
165 macro(deleteWordForward) \ |
|
166 macro(ignoreSpelling) \ |
|
167 macro(indent) \ |
|
168 macro(insertBacktab) \ |
|
169 macro(insertNewline) \ |
|
170 macro(insertNewlineIgnoringFieldEditor) \ |
|
171 macro(insertParagraphSeparator) \ |
|
172 macro(insertTab) \ |
|
173 macro(insertTabIgnoringFieldEditor) \ |
|
174 macro(lowercaseWord) \ |
|
175 macro(moveBackward) \ |
|
176 macro(moveBackwardAndModifySelection) \ |
|
177 macro(moveDown) \ |
|
178 macro(moveDownAndModifySelection) \ |
|
179 macro(moveForward) \ |
|
180 macro(moveForwardAndModifySelection) \ |
|
181 macro(moveLeft) \ |
|
182 macro(moveLeftAndModifySelection) \ |
|
183 macro(moveRight) \ |
|
184 macro(moveRightAndModifySelection) \ |
|
185 macro(moveToBeginningOfDocument) \ |
|
186 macro(moveToBeginningOfDocumentAndModifySelection) \ |
|
187 macro(moveToBeginningOfSentence) \ |
|
188 macro(moveToBeginningOfSentenceAndModifySelection) \ |
|
189 macro(moveToBeginningOfLine) \ |
|
190 macro(moveToBeginningOfLineAndModifySelection) \ |
|
191 macro(moveToBeginningOfParagraph) \ |
|
192 macro(moveToBeginningOfParagraphAndModifySelection) \ |
|
193 macro(moveToEndOfDocument) \ |
|
194 macro(moveToEndOfDocumentAndModifySelection) \ |
|
195 macro(moveToEndOfLine) \ |
|
196 macro(moveToEndOfLineAndModifySelection) \ |
|
197 macro(moveToEndOfParagraph) \ |
|
198 macro(moveToEndOfParagraphAndModifySelection) \ |
|
199 macro(moveToEndOfSentence) \ |
|
200 macro(moveToEndOfSentenceAndModifySelection) \ |
|
201 macro(moveUp) \ |
|
202 macro(moveUpAndModifySelection) \ |
|
203 macro(moveWordBackward) \ |
|
204 macro(moveWordBackwardAndModifySelection) \ |
|
205 macro(moveWordForward) \ |
|
206 macro(moveWordForwardAndModifySelection) \ |
|
207 macro(moveWordLeft) \ |
|
208 macro(moveWordLeftAndModifySelection) \ |
|
209 macro(moveWordRight) \ |
|
210 macro(moveWordRightAndModifySelection) \ |
|
211 macro(outdent) \ |
|
212 macro(pageDown) \ |
|
213 macro(pageUp) \ |
|
214 macro(paste) \ |
|
215 macro(pasteAsPlainText) \ |
|
216 macro(pasteAsRichText) \ |
|
217 macro(pasteFont) \ |
|
218 macro(performFindPanelAction) \ |
|
219 macro(scrollLineDown) \ |
|
220 macro(scrollLineUp) \ |
|
221 macro(scrollPageDown) \ |
|
222 macro(scrollPageUp) \ |
|
223 macro(scrollToBeginningOfDocument) \ |
|
224 macro(scrollToEndOfDocument) \ |
|
225 macro(selectAll) \ |
|
226 macro(selectWord) \ |
|
227 macro(selectSentence) \ |
|
228 macro(selectLine) \ |
|
229 macro(selectParagraph) \ |
|
230 macro(showGuessPanel) \ |
|
231 macro(startSpeaking) \ |
|
232 macro(stopSpeaking) \ |
|
233 macro(subscript) \ |
|
234 macro(superscript) \ |
|
235 macro(underline) \ |
|
236 macro(unscript) \ |
|
237 macro(uppercaseWord) \ |
|
238 macro(yank) \ |
|
239 macro(yankAndSelect) \ |
|
240 |
|
241 #define WebKitOriginalTopPrintingMarginKey @"WebKitOriginalTopMargin" |
|
242 #define WebKitOriginalBottomPrintingMarginKey @"WebKitOriginalBottomMargin" |
|
243 |
|
244 static BOOL s_didSetCacheModel; |
|
245 static WebCacheModel s_cacheModel = WebCacheModelDocumentViewer; |
|
246 |
|
247 static BOOL applicationIsTerminating; |
|
248 static int pluginDatabaseClientCount = 0; |
|
249 |
|
250 @interface NSSpellChecker (AppKitSecretsIKnow) |
|
251 - (void)_preflightChosenSpellServer; |
|
252 @end |
|
253 |
|
254 @interface NSView (AppKitSecretsIKnow) |
|
255 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types; |
|
256 - (void)_autoscrollForDraggingInfo:(id)dragInfo timeDelta:(NSTimeInterval)repeatDelta; |
|
257 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)dragInfo; |
|
258 @end |
|
259 |
|
260 @interface NSWindow (AppKitSecretsIKnow) |
|
261 - (id)_oldFirstResponderBeforeBecoming; |
|
262 @end |
|
263 |
|
264 @interface NSObject (ValidateWithoutDelegate) |
|
265 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item; |
|
266 @end |
|
267 |
|
268 @interface _WebSafeForwarder : NSObject |
|
269 { |
|
270 id target; // Non-retained. Don't retain delegates. |
|
271 id defaultTarget; |
|
272 BOOL catchExceptions; |
|
273 } |
|
274 - (id)initWithTarget:(id)target defaultTarget:(id)defaultTarget catchExceptions:(BOOL)catchExceptions; |
|
275 @end |
|
276 |
|
277 @interface WebViewPrivate : NSObject |
|
278 { |
|
279 @public |
|
280 Page* page; |
|
281 |
|
282 id UIDelegate; |
|
283 id UIDelegateForwarder; |
|
284 id resourceProgressDelegate; |
|
285 id downloadDelegate; |
|
286 id policyDelegate; |
|
287 id policyDelegateForwarder; |
|
288 id frameLoadDelegate; |
|
289 id frameLoadDelegateForwarder; |
|
290 id <WebFormDelegate> formDelegate; |
|
291 id editingDelegate; |
|
292 id editingDelegateForwarder; |
|
293 id scriptDebugDelegate; |
|
294 id scriptDebugDelegateForwarder; |
|
295 |
|
296 BOOL allowsUndo; |
|
297 |
|
298 float textSizeMultiplier; |
|
299 |
|
300 NSString *applicationNameForUserAgent; |
|
301 String* userAgent; |
|
302 BOOL userAgentOverridden; |
|
303 |
|
304 WebPreferences *preferences; |
|
305 BOOL useSiteSpecificSpoofing; |
|
306 |
|
307 NSWindow *hostWindow; |
|
308 |
|
309 int programmaticFocusCount; |
|
310 |
|
311 WebResourceDelegateImplementationCache resourceLoadDelegateImplementations; |
|
312 WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations; |
|
313 |
|
314 void *observationInfo; |
|
315 |
|
316 BOOL closed; |
|
317 BOOL shouldCloseWithWindow; |
|
318 BOOL mainFrameDocumentReady; |
|
319 BOOL drawsBackground; |
|
320 BOOL editable; |
|
321 BOOL tabKeyCyclesThroughElementsChanged; |
|
322 BOOL becomingFirstResponder; |
|
323 BOOL becomingFirstResponderFromOutside; |
|
324 BOOL hoverFeedbackSuspended; |
|
325 BOOL usesPageCache; |
|
326 BOOL catchesDelegateExceptions; |
|
327 |
|
328 NSColor *backgroundColor; |
|
329 |
|
330 NSString *mediaStyle; |
|
331 |
|
332 BOOL hasSpellCheckerDocumentTag; |
|
333 NSInteger spellCheckerDocumentTag; |
|
334 |
|
335 BOOL smartInsertDeleteEnabled; |
|
336 |
|
337 BOOL dashboardBehaviorAlwaysSendMouseEventsToAllWindows; |
|
338 BOOL dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns; |
|
339 BOOL dashboardBehaviorAlwaysAcceptsFirstMouse; |
|
340 BOOL dashboardBehaviorAllowWheelScrolling; |
|
341 |
|
342 // WebKit has both a global plug-in database and a separate, per WebView plug-in database. Dashboard uses the per WebView database. |
|
343 WebPluginDatabase *pluginDatabase; |
|
344 |
|
345 HashMap<unsigned long, RetainPtr<id> >* identifierMap; |
|
346 } |
|
347 @end |
|
348 |
|
349 @interface WebView (WebFileInternal) |
|
350 + (void)_setCacheModel:(WebCacheModel)cacheModel; |
|
351 + (WebCacheModel)_cacheModel; |
|
352 - (WebFrame *)_selectedOrMainFrame; |
|
353 - (WebFrameBridge *)_bridgeForSelectedOrMainFrame; |
|
354 - (BOOL)_isLoading; |
|
355 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point; |
|
356 - (WebFrame *)_focusedFrame; |
|
357 + (void)_preflightSpellChecker; |
|
358 - (BOOL)_continuousCheckingAllowed; |
|
359 - (NSResponder *)_responderForResponderOperations; |
|
360 - (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor; |
|
361 - (void)_notifyTextSizeMultiplierChanged; |
|
362 @end |
|
363 |
|
364 @interface WebView (WebCallDelegateFunctions) |
|
365 @end |
|
366 |
|
367 NSString *WebElementDOMNodeKey = @"WebElementDOMNode"; |
|
368 NSString *WebElementFrameKey = @"WebElementFrame"; |
|
369 NSString *WebElementImageKey = @"WebElementImage"; |
|
370 NSString *WebElementImageAltStringKey = @"WebElementImageAltString"; |
|
371 NSString *WebElementImageRectKey = @"WebElementImageRect"; |
|
372 NSString *WebElementImageURLKey = @"WebElementImageURL"; |
|
373 NSString *WebElementIsSelectedKey = @"WebElementIsSelected"; |
|
374 NSString *WebElementLinkLabelKey = @"WebElementLinkLabel"; |
|
375 NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame"; |
|
376 NSString *WebElementLinkTitleKey = @"WebElementLinkTitle"; |
|
377 NSString *WebElementLinkURLKey = @"WebElementLinkURL"; |
|
378 NSString *WebElementSpellingToolTipKey = @"WebElementSpellingToolTip"; |
|
379 NSString *WebElementTitleKey = @"WebElementTitle"; |
|
380 NSString *WebElementLinkIsLiveKey = @"WebElementLinkIsLive"; |
|
381 NSString *WebElementIsContentEditableKey = @"WebElementIsContentEditableKey"; |
|
382 |
|
383 NSString *WebViewProgressStartedNotification = @"WebProgressStartedNotification"; |
|
384 NSString *WebViewProgressEstimateChangedNotification = @"WebProgressEstimateChangedNotification"; |
|
385 NSString *WebViewProgressFinishedNotification = @"WebProgressFinishedNotification"; |
|
386 |
|
387 NSString * const WebViewDidBeginEditingNotification = @"WebViewDidBeginEditingNotification"; |
|
388 NSString * const WebViewDidChangeNotification = @"WebViewDidChangeNotification"; |
|
389 NSString * const WebViewDidEndEditingNotification = @"WebViewDidEndEditingNotification"; |
|
390 NSString * const WebViewDidChangeTypingStyleNotification = @"WebViewDidChangeTypingStyleNotification"; |
|
391 NSString * const WebViewDidChangeSelectionNotification = @"WebViewDidChangeSelectionNotification"; |
|
392 |
|
393 enum { WebViewVersion = 4 }; |
|
394 |
|
395 #define timedLayoutSize 4096 |
|
396 |
|
397 static NSMutableSet *schemesWithRepresentationsSet; |
|
398 |
|
399 NSString *_WebCanGoBackKey = @"canGoBack"; |
|
400 NSString *_WebCanGoForwardKey = @"canGoForward"; |
|
401 NSString *_WebEstimatedProgressKey = @"estimatedProgress"; |
|
402 NSString *_WebIsLoadingKey = @"isLoading"; |
|
403 NSString *_WebMainFrameIconKey = @"mainFrameIcon"; |
|
404 NSString *_WebMainFrameTitleKey = @"mainFrameTitle"; |
|
405 NSString *_WebMainFrameURLKey = @"mainFrameURL"; |
|
406 NSString *_WebMainFrameDocumentKey = @"mainFrameDocument"; |
|
407 |
|
408 @interface WebProgressItem : NSObject |
|
409 { |
|
410 @public |
|
411 long long bytesReceived; |
|
412 long long estimatedLength; |
|
413 } |
|
414 @end |
|
415 |
|
416 @implementation WebProgressItem |
|
417 @end |
|
418 |
|
419 static BOOL continuousSpellCheckingEnabled; |
|
420 #ifndef BUILDING_ON_TIGER |
|
421 static BOOL grammarCheckingEnabled; |
|
422 #endif |
|
423 |
|
424 @implementation WebViewPrivate |
|
425 |
|
426 #ifndef BUILDING_ON_TIGER |
|
427 + (void)initialize |
|
428 { |
|
429 WebCoreObjCFinalizeOnMainThread(self); |
|
430 } |
|
431 #endif |
|
432 |
|
433 - init |
|
434 { |
|
435 self = [super init]; |
|
436 if (!self) |
|
437 return nil; |
|
438 allowsUndo = YES; |
|
439 textSizeMultiplier = 1; |
|
440 dashboardBehaviorAllowWheelScrolling = YES; |
|
441 shouldCloseWithWindow = objc_collecting_enabled(); |
|
442 continuousSpellCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebContinuousSpellCheckingEnabled]; |
|
443 |
|
444 #ifndef BUILDING_ON_TIGER |
|
445 grammarCheckingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:WebGrammarCheckingEnabled]; |
|
446 #endif |
|
447 userAgent = new String; |
|
448 |
|
449 usesPageCache = YES; |
|
450 |
|
451 identifierMap = new HashMap<unsigned long, RetainPtr<id> >(); |
|
452 pluginDatabaseClientCount++; |
|
453 |
|
454 return self; |
|
455 } |
|
456 |
|
457 - (void)dealloc |
|
458 { |
|
459 ASSERT(!page); |
|
460 ASSERT(!preferences); |
|
461 |
|
462 delete userAgent; |
|
463 delete identifierMap; |
|
464 |
|
465 [applicationNameForUserAgent release]; |
|
466 [backgroundColor release]; |
|
467 |
|
468 [hostWindow release]; |
|
469 |
|
470 [policyDelegateForwarder release]; |
|
471 [UIDelegateForwarder release]; |
|
472 [frameLoadDelegateForwarder release]; |
|
473 [editingDelegateForwarder release]; |
|
474 [scriptDebugDelegateForwarder release]; |
|
475 |
|
476 [mediaStyle release]; |
|
477 |
|
478 [super dealloc]; |
|
479 } |
|
480 |
|
481 - (void)finalize |
|
482 { |
|
483 ASSERT_MAIN_THREAD(); |
|
484 |
|
485 delete userAgent; |
|
486 delete identifierMap; |
|
487 |
|
488 [super finalize]; |
|
489 } |
|
490 |
|
491 @end |
|
492 |
|
493 @implementation WebView (AllWebViews) |
|
494 |
|
495 static CFSetCallBacks NonRetainingSetCallbacks = { |
|
496 0, |
|
497 NULL, |
|
498 NULL, |
|
499 CFCopyDescription, |
|
500 CFEqual, |
|
501 CFHash |
|
502 }; |
|
503 |
|
504 static CFMutableSetRef allWebViewsSet; |
|
505 |
|
506 + (void)_makeAllWebViewsPerformSelector:(SEL)selector |
|
507 { |
|
508 if (!allWebViewsSet) |
|
509 return; |
|
510 |
|
511 [(NSMutableSet *)allWebViewsSet makeObjectsPerformSelector:selector]; |
|
512 } |
|
513 |
|
514 - (void)_removeFromAllWebViewsSet |
|
515 { |
|
516 if (allWebViewsSet) |
|
517 CFSetRemoveValue(allWebViewsSet, self); |
|
518 } |
|
519 |
|
520 - (void)_addToAllWebViewsSet |
|
521 { |
|
522 if (!allWebViewsSet) |
|
523 allWebViewsSet = CFSetCreateMutable(NULL, 0, &NonRetainingSetCallbacks); |
|
524 |
|
525 CFSetSetValue(allWebViewsSet, self); |
|
526 } |
|
527 |
|
528 @end |
|
529 |
|
530 @implementation WebView (WebPrivate) |
|
531 |
|
532 #ifdef DEBUG_WIDGET_DRAWING |
|
533 static bool debugWidget = true; |
|
534 - (void)drawRect:(NSRect)rect |
|
535 { |
|
536 [[NSColor blueColor] set]; |
|
537 NSRectFill (rect); |
|
538 |
|
539 NSRect htmlViewRect = [[[[self mainFrame] frameView] documentView] frame]; |
|
540 |
|
541 if (debugWidget) { |
|
542 while (debugWidget) { |
|
543 sleep (1); |
|
544 } |
|
545 } |
|
546 |
|
547 NSLog (@"%s: rect: (%0.f,%0.f) %0.f %0.f, htmlViewRect: (%0.f,%0.f) %0.f %0.f\n", |
|
548 __PRETTY_FUNCTION__, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, |
|
549 htmlViewRect.origin.x, htmlViewRect.origin.y, htmlViewRect.size.width, htmlViewRect.size.height |
|
550 ); |
|
551 |
|
552 [super drawRect:rect]; |
|
553 } |
|
554 #endif |
|
555 |
|
556 + (BOOL)_developerExtrasEnabled |
|
557 { |
|
558 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; |
|
559 if ([defaults boolForKey:@"DisableWebKitDeveloperExtras"]) |
|
560 return NO; |
|
561 #ifdef NDEBUG |
|
562 BOOL enableDebugger = [defaults boolForKey:@"WebKitDeveloperExtras"]; |
|
563 if (!enableDebugger) |
|
564 enableDebugger = [defaults boolForKey:@"IncludeDebugMenu"]; |
|
565 return enableDebugger; |
|
566 #else |
|
567 return YES; // always enable in debug builds |
|
568 #endif |
|
569 } |
|
570 |
|
571 + (BOOL)_scriptDebuggerEnabled |
|
572 { |
|
573 #ifdef NDEBUG |
|
574 return [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitScriptDebuggerEnabled"]; |
|
575 #else |
|
576 return YES; // always enable in debug builds |
|
577 #endif |
|
578 } |
|
579 |
|
580 + (NSArray *)_supportedMIMETypes |
|
581 { |
|
582 // Load the plug-in DB allowing plug-ins to install types. |
|
583 [WebPluginDatabase sharedDatabase]; |
|
584 return [[WebFrameView _viewTypesAllowImageTypeOmission:NO] allKeys]; |
|
585 } |
|
586 |
|
587 + (NSArray *)_supportedFileExtensions |
|
588 { |
|
589 NSMutableSet *extensions = [[NSMutableSet alloc] init]; |
|
590 NSArray *MIMETypes = [self _supportedMIMETypes]; |
|
591 NSEnumerator *enumerator = [MIMETypes objectEnumerator]; |
|
592 NSString *MIMEType; |
|
593 while ((MIMEType = [enumerator nextObject]) != nil) { |
|
594 NSArray *extensionsForType = WKGetExtensionsForMIMEType(MIMEType); |
|
595 if (extensionsForType) { |
|
596 [extensions addObjectsFromArray:extensionsForType]; |
|
597 } |
|
598 } |
|
599 NSArray *uniqueExtensions = [extensions allObjects]; |
|
600 [extensions release]; |
|
601 return uniqueExtensions; |
|
602 } |
|
603 |
|
604 + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType; |
|
605 { |
|
606 MIMEType = [MIMEType lowercaseString]; |
|
607 Class viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; |
|
608 Class repClass = [[WebDataSource _repTypesAllowImageTypeOmission:YES] _webkit_objectForMIMEType:MIMEType]; |
|
609 |
|
610 if (!viewClass || !repClass || [[WebPDFView supportedMIMETypes] containsObject:MIMEType]) { |
|
611 // Our optimization to avoid loading the plug-in DB and image types for the HTML case failed. |
|
612 // Load the plug-in DB allowing plug-ins to install types. |
|
613 [WebPluginDatabase sharedDatabase]; |
|
614 |
|
615 // Load the image types and get the view class and rep class. This should be the fullest picture of all handled types. |
|
616 viewClass = [[WebFrameView _viewTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; |
|
617 repClass = [[WebDataSource _repTypesAllowImageTypeOmission:NO] _webkit_objectForMIMEType:MIMEType]; |
|
618 } |
|
619 |
|
620 if (viewClass && repClass) { |
|
621 // Special-case WebHTMLView for text types that shouldn't be shown. |
|
622 if (viewClass == [WebHTMLView class] && |
|
623 repClass == [WebHTMLRepresentation class] && |
|
624 [[WebHTMLView unsupportedTextMIMETypes] containsObject:MIMEType]) { |
|
625 return NO; |
|
626 } |
|
627 if (vClass) |
|
628 *vClass = viewClass; |
|
629 if (rClass) |
|
630 *rClass = repClass; |
|
631 return YES; |
|
632 } |
|
633 |
|
634 return NO; |
|
635 } |
|
636 |
|
637 - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType; |
|
638 { |
|
639 if ([[self class] _viewClass:vClass andRepresentationClass:rClass forMIMEType:MIMEType]) |
|
640 return YES; |
|
641 |
|
642 if (_private->pluginDatabase) { |
|
643 WebBasePluginPackage *pluginPackage = [_private->pluginDatabase pluginForMIMEType:MIMEType]; |
|
644 if (pluginPackage) { |
|
645 if (vClass) |
|
646 *vClass = [WebHTMLView class]; |
|
647 if (rClass) |
|
648 *rClass = [WebHTMLRepresentation class]; |
|
649 return YES; |
|
650 } |
|
651 } |
|
652 |
|
653 return NO; |
|
654 } |
|
655 |
|
656 + (void)_setAlwaysUseATSU:(BOOL)f |
|
657 { |
|
658 WebCoreSetAlwaysUseATSU(f); |
|
659 } |
|
660 |
|
661 + (BOOL)canShowFile:(NSString *)path |
|
662 { |
|
663 return [[self class] canShowMIMEType:[WebView _MIMETypeForFile:path]]; |
|
664 } |
|
665 |
|
666 + (NSString *)suggestedFileExtensionForMIMEType:(NSString *)type |
|
667 { |
|
668 return WKGetPreferredExtensionForMIMEType(type); |
|
669 } |
|
670 |
|
671 - (BOOL)_isClosed |
|
672 { |
|
673 if (!_private || _private->closed) |
|
674 return YES; |
|
675 return NO; |
|
676 } |
|
677 |
|
678 - (void)_close |
|
679 { |
|
680 if (!_private || _private->closed) |
|
681 return; |
|
682 |
|
683 FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader]; |
|
684 if (mainFrameLoader) |
|
685 mainFrameLoader->detachFromParent(); |
|
686 |
|
687 [self _removeFromAllWebViewsSet]; |
|
688 [self setGroupName:nil]; |
|
689 [self setHostWindow:nil]; |
|
690 |
|
691 [self setDownloadDelegate:nil]; |
|
692 [self setEditingDelegate:nil]; |
|
693 [self setFrameLoadDelegate:nil]; |
|
694 [self setPolicyDelegate:nil]; |
|
695 [self setResourceLoadDelegate:nil]; |
|
696 [self setScriptDebugDelegate:nil]; |
|
697 [self setUIDelegate:nil]; |
|
698 |
|
699 // setHostWindow:nil must be called before this value is set (see 5408186) |
|
700 _private->closed = YES; |
|
701 |
|
702 // To avoid leaks, call removeDragCaret in case it wasn't called after moveDragCaretToPoint. |
|
703 [self removeDragCaret]; |
|
704 |
|
705 // Deleteing the WebCore::Page will clear the page cache so we call destroy on |
|
706 // all the plug-ins in the page cache to break any retain cycles. |
|
707 // See comment in HistoryItem::releaseAllPendingPageCaches() for more information. |
|
708 delete _private->page; |
|
709 _private->page = 0; |
|
710 |
|
711 if (_private->hasSpellCheckerDocumentTag) { |
|
712 [[NSSpellChecker sharedSpellChecker] closeSpellDocumentWithTag:_private->spellCheckerDocumentTag]; |
|
713 _private->hasSpellCheckerDocumentTag = NO; |
|
714 } |
|
715 |
|
716 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
|
717 |
|
718 [WebPreferences _removeReferenceForIdentifier:[self preferencesIdentifier]]; |
|
719 |
|
720 WebPreferences *preferences = _private->preferences; |
|
721 _private->preferences = nil; |
|
722 [preferences didRemoveFromWebView]; |
|
723 [preferences release]; |
|
724 |
|
725 pluginDatabaseClientCount--; |
|
726 |
|
727 // Make sure to close both sets of plug-ins databases because plug-ins need an opportunity to clean up files, etc. |
|
728 |
|
729 // Unload the WebView local plug-in database. |
|
730 if (_private->pluginDatabase) { |
|
731 [_private->pluginDatabase close]; |
|
732 [_private->pluginDatabase release]; |
|
733 _private->pluginDatabase = nil; |
|
734 } |
|
735 |
|
736 // Keep the global plug-in database active until the app terminates to avoid having to reload plug-in bundles. |
|
737 if (!pluginDatabaseClientCount && applicationIsTerminating) |
|
738 [WebPluginDatabase closeSharedDatabase]; |
|
739 } |
|
740 |
|
741 + (NSString *)_MIMETypeForFile:(NSString *)path |
|
742 { |
|
743 NSString *extension = [path pathExtension]; |
|
744 NSString *MIMEType = nil; |
|
745 |
|
746 // Get the MIME type from the extension. |
|
747 if ([extension length] != 0) { |
|
748 MIMEType = WKGetMIMETypeForExtension(extension); |
|
749 } |
|
750 |
|
751 // If we can't get a known MIME type from the extension, sniff. |
|
752 if ([MIMEType length] == 0 || [MIMEType isEqualToString:@"application/octet-stream"]) { |
|
753 NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path]; |
|
754 NSData *data = [handle readDataOfLength:WEB_GUESS_MIME_TYPE_PEEK_LENGTH]; |
|
755 [handle closeFile]; |
|
756 if ([data length] != 0) { |
|
757 MIMEType = [data _webkit_guessedMIMEType]; |
|
758 } |
|
759 if ([MIMEType length] == 0) { |
|
760 MIMEType = @"application/octet-stream"; |
|
761 } |
|
762 } |
|
763 |
|
764 return MIMEType; |
|
765 } |
|
766 |
|
767 - (WebDownload *)_downloadURL:(NSURL *)URL |
|
768 { |
|
769 ASSERT(URL); |
|
770 |
|
771 NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL]; |
|
772 WebDownload *download = [WebDownload _downloadWithRequest:request |
|
773 delegate:_private->downloadDelegate |
|
774 directory:nil]; |
|
775 [request release]; |
|
776 |
|
777 return download; |
|
778 } |
|
779 |
|
780 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request |
|
781 { |
|
782 WebView *newWindowWebView = CallUIDelegate(self, @selector(webView:createWebViewWithRequest:), request); |
|
783 if (!newWindowWebView) |
|
784 return nil; |
|
785 |
|
786 CallUIDelegate(newWindowWebView, @selector(webViewShow:)); |
|
787 return newWindowWebView; |
|
788 } |
|
789 |
|
790 - (WebCore::Page*)page |
|
791 { |
|
792 return _private->page; |
|
793 } |
|
794 |
|
795 - (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items |
|
796 { |
|
797 NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate] webView:self contextMenuItemsForElement:element defaultMenuItems:items]; |
|
798 |
|
799 NSArray *menuItems = CallUIDelegate(self, @selector(webView:contextMenuItemsForElement:defaultMenuItems:), element, defaultMenuItems); |
|
800 if (!menuItems) |
|
801 return nil; |
|
802 |
|
803 unsigned count = [menuItems count]; |
|
804 if (!count) |
|
805 return nil; |
|
806 |
|
807 NSMenu *menu = [[NSMenu alloc] init]; |
|
808 for (unsigned i = 0; i < count; i++) |
|
809 [menu addItem:[menuItems objectAtIndex:i]]; |
|
810 |
|
811 return [menu autorelease]; |
|
812 } |
|
813 |
|
814 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(NSUInteger)modifierFlags |
|
815 { |
|
816 // We originally intended to call this delegate method sometimes with a nil dictionary, but due to |
|
817 // a bug dating back to WebKit 1.0 this delegate was never called with nil! Unfortunately we can't |
|
818 // start calling this with nil since it will break Adobe Help Viewer, and possibly other clients. |
|
819 if (!dictionary) |
|
820 return; |
|
821 CallUIDelegate(self, @selector(webView:mouseDidMoveOverElement:modifierFlags:), dictionary, modifierFlags); |
|
822 } |
|
823 |
|
824 - (void)_loadBackForwardListFromOtherView:(WebView *)otherView |
|
825 { |
|
826 if (!_private->page) |
|
827 return; |
|
828 |
|
829 if (!otherView->_private->page) |
|
830 return; |
|
831 |
|
832 // It turns out the right combination of behavior is done with the back/forward load |
|
833 // type. (See behavior matrix at the top of WebFramePrivate.) So we copy all the items |
|
834 // in the back forward list, and go to the current one. |
|
835 |
|
836 BackForwardList* backForwardList = _private->page->backForwardList(); |
|
837 ASSERT(!backForwardList->currentItem()); // destination list should be empty |
|
838 |
|
839 BackForwardList* otherBackForwardList = otherView->_private->page->backForwardList(); |
|
840 if (!otherBackForwardList->currentItem()) |
|
841 return; // empty back forward list, bail |
|
842 |
|
843 HistoryItem* newItemToGoTo = 0; |
|
844 |
|
845 int lastItemIndex = otherBackForwardList->forwardListCount(); |
|
846 for (int i = -otherBackForwardList->backListCount(); i <= lastItemIndex; ++i) { |
|
847 if (i == 0) { |
|
848 // If this item is showing , save away its current scroll and form state, |
|
849 // since that might have changed since loading and it is normally not saved |
|
850 // until we leave that page. |
|
851 otherView->_private->page->mainFrame()->loader()->saveDocumentAndScrollState(); |
|
852 } |
|
853 RefPtr<HistoryItem> newItem = otherBackForwardList->itemAtIndex(i)->copy(); |
|
854 if (i == 0) |
|
855 newItemToGoTo = newItem.get(); |
|
856 backForwardList->addItem(newItem.release()); |
|
857 } |
|
858 |
|
859 ASSERT(newItemToGoTo); |
|
860 _private->page->goToItem(newItemToGoTo, FrameLoadTypeIndexedBackForward); |
|
861 } |
|
862 |
|
863 - (void)_setFormDelegate: (id<WebFormDelegate>)delegate |
|
864 { |
|
865 _private->formDelegate = delegate; |
|
866 } |
|
867 |
|
868 - (id<WebFormDelegate>)_formDelegate |
|
869 { |
|
870 return _private->formDelegate; |
|
871 } |
|
872 |
|
873 - (BOOL)_needsAdobeFrameReloadingQuirk |
|
874 { |
|
875 static BOOL checked = NO; |
|
876 static BOOL needsQuirk = NO; |
|
877 |
|
878 if (checked) |
|
879 return needsQuirk; |
|
880 |
|
881 needsQuirk = WKAppVersionCheckLessThan(@"com.adobe.Acrobat", -1, 9.0) |
|
882 || WKAppVersionCheckLessThan(@"com.adobe.Acrobat.Pro", -1, 9.0) |
|
883 || WKAppVersionCheckLessThan(@"com.adobe.Reader", -1, 9.0) |
|
884 || WKAppVersionCheckLessThan(@"com.adobe.distiller", -1, 9.0) |
|
885 || WKAppVersionCheckLessThan(@"com.adobe.Contribute", -1, 4.2) |
|
886 || WKAppVersionCheckLessThan(@"com.adobe.dreamweaver-9.0", -1, 9.1) |
|
887 || WKAppVersionCheckLessThan(@"com.macromedia.fireworks", -1, 9.1) |
|
888 || WKAppVersionCheckLessThan(@"com.adobe.InCopy", -1, 5.1) |
|
889 || WKAppVersionCheckLessThan(@"com.adobe.InDesign", -1, 5.1) |
|
890 || WKAppVersionCheckLessThan(@"com.adobe.Soundbooth", -1, 2); |
|
891 |
|
892 return needsQuirk; |
|
893 } |
|
894 |
|
895 - (void)_preferencesChangedNotification:(NSNotification *)notification |
|
896 { |
|
897 WebPreferences *preferences = (WebPreferences *)[notification object]; |
|
898 ASSERT(preferences == [self preferences]); |
|
899 |
|
900 if (!_private->userAgentOverridden) |
|
901 *_private->userAgent = String(); |
|
902 |
|
903 // Cache this value so we don't have to read NSUserDefaults on each page load |
|
904 _private->useSiteSpecificSpoofing = [preferences _useSiteSpecificSpoofing]; |
|
905 |
|
906 // Update corresponding WebCore Settings object. |
|
907 if (!_private->page) |
|
908 return; |
|
909 |
|
910 Settings* settings = _private->page->settings(); |
|
911 |
|
912 settings->setCursiveFontFamily([preferences cursiveFontFamily]); |
|
913 settings->setDefaultFixedFontSize([preferences defaultFixedFontSize]); |
|
914 settings->setDefaultFontSize([preferences defaultFontSize]); |
|
915 settings->setDefaultTextEncodingName([preferences defaultTextEncodingName]); |
|
916 settings->setFantasyFontFamily([preferences fantasyFontFamily]); |
|
917 settings->setFixedFontFamily([preferences fixedFontFamily]); |
|
918 settings->setForceFTPDirectoryListings([preferences _forceFTPDirectoryListings]); |
|
919 settings->setFTPDirectoryTemplatePath([preferences _ftpDirectoryTemplatePath]); |
|
920 settings->setJavaEnabled([preferences isJavaEnabled]); |
|
921 settings->setJavaScriptEnabled([preferences isJavaScriptEnabled]); |
|
922 settings->setJavaScriptCanOpenWindowsAutomatically([preferences javaScriptCanOpenWindowsAutomatically]); |
|
923 settings->setMinimumFontSize([preferences minimumFontSize]); |
|
924 settings->setMinimumLogicalFontSize([preferences minimumLogicalFontSize]); |
|
925 settings->setPluginsEnabled([preferences arePlugInsEnabled]); |
|
926 settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]); |
|
927 settings->setSansSerifFontFamily([preferences sansSerifFontFamily]); |
|
928 settings->setSerifFontFamily([preferences serifFontFamily]); |
|
929 settings->setStandardFontFamily([preferences standardFontFamily]); |
|
930 settings->setLoadsImagesAutomatically([preferences loadsImagesAutomatically]); |
|
931 settings->setShouldPrintBackgrounds([preferences shouldPrintBackgrounds]); |
|
932 settings->setTextAreasAreResizable([preferences textAreasAreResizable]); |
|
933 settings->setShrinksStandaloneImagesToFit([preferences shrinksStandaloneImagesToFit]); |
|
934 settings->setEditableLinkBehavior(core([preferences editableLinkBehavior])); |
|
935 settings->setDOMPasteAllowed([preferences isDOMPasteAllowed]); |
|
936 settings->setUsesPageCache([self usesPageCache]); |
|
937 settings->setShowsURLsInToolTips([preferences showsURLsInToolTips]); |
|
938 settings->setDeveloperExtrasEnabled([WebView _developerExtrasEnabled]); |
|
939 if ([preferences userStyleSheetEnabled]) { |
|
940 NSString* location = [[preferences userStyleSheetLocation] _web_originalDataAsString]; |
|
941 settings->setUserStyleSheetLocation([NSURL URLWithString:(location ? location : @"")]); |
|
942 } else |
|
943 settings->setUserStyleSheetLocation([NSURL URLWithString:@""]); |
|
944 settings->setNeedsAdobeFrameReloadingQuirk([self _needsAdobeFrameReloadingQuirk]); |
|
945 } |
|
946 |
|
947 static inline IMP getMethod(id o, SEL s) |
|
948 { |
|
949 return [o respondsToSelector:s] ? [o methodForSelector:s] : 0; |
|
950 } |
|
951 |
|
952 - (void)_cacheResourceLoadDelegateImplementations |
|
953 { |
|
954 WebResourceDelegateImplementationCache *cache = &_private->resourceLoadDelegateImplementations; |
|
955 id delegate = _private->resourceProgressDelegate; |
|
956 |
|
957 cache->didCancelAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)); |
|
958 cache->didFailLoadingWithErrorFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:)); |
|
959 cache->didFinishLoadingFromDataSourceFunc = getMethod(delegate, @selector(webView:resource:didFinishLoadingFromDataSource:)); |
|
960 cache->didLoadResourceFromMemoryCacheFunc = getMethod(delegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:)); |
|
961 cache->didReceiveAuthenticationChallengeFunc = getMethod(delegate, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:)); |
|
962 cache->didReceiveContentLengthFunc = getMethod(delegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:)); |
|
963 cache->didReceiveResponseFunc = getMethod(delegate, @selector(webView:resource:didReceiveResponse:fromDataSource:)); |
|
964 cache->identifierForRequestFunc = getMethod(delegate, @selector(webView:identifierForInitialRequest:fromDataSource:)); |
|
965 cache->plugInFailedWithErrorFunc = getMethod(delegate, @selector(webView:plugInFailedWithError:dataSource:)); |
|
966 cache->willCacheResponseFunc = getMethod(delegate, @selector(webView:resource:willCacheResponse:fromDataSource:)); |
|
967 cache->willSendRequestFunc = getMethod(delegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:)); |
|
968 } |
|
969 |
|
970 WebResourceDelegateImplementationCache WebViewGetResourceLoadDelegateImplementations(WebView *webView) |
|
971 { |
|
972 return webView->_private->resourceLoadDelegateImplementations; |
|
973 } |
|
974 |
|
975 - (void)_cacheFrameLoadDelegateImplementations |
|
976 { |
|
977 WebFrameLoadDelegateImplementationCache *cache = &_private->frameLoadDelegateImplementations; |
|
978 id delegate = _private->frameLoadDelegate; |
|
979 |
|
980 cache->didCancelClientRedirectForFrameFunc = getMethod(delegate, @selector(webView:didCancelClientRedirectForFrame:)); |
|
981 cache->didChangeLocationWithinPageForFrameFunc = getMethod(delegate, @selector(webView:didChangeLocationWithinPageForFrame:)); |
|
982 cache->didClearWindowObjectForFrameFunc = getMethod(delegate, @selector(webView:didClearWindowObject:forFrame:)); |
|
983 cache->didCommitLoadForFrameFunc = getMethod(delegate, @selector(webView:didCommitLoadForFrame:)); |
|
984 cache->didFailLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailLoadWithError:forFrame:)); |
|
985 cache->didFailProvisionalLoadWithErrorForFrameFunc = getMethod(delegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:)); |
|
986 cache->didFinishDocumentLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishDocumentLoadForFrame:)); |
|
987 cache->didFinishLoadForFrameFunc = getMethod(delegate, @selector(webView:didFinishLoadForFrame:)); |
|
988 cache->didFirstLayoutInFrameFunc = getMethod(delegate, @selector(webView:didFirstLayoutInFrame:)); |
|
989 cache->didHandleOnloadEventsForFrameFunc = getMethod(delegate, @selector(webView:didHandleOnloadEventsForFrame:)); |
|
990 cache->didReceiveIconForFrameFunc = getMethod(delegate, @selector(webView:didReceiveIcon:forFrame:)); |
|
991 cache->didReceiveServerRedirectForProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:)); |
|
992 cache->didReceiveTitleForFrameFunc = getMethod(delegate, @selector(webView:didReceiveTitle:forFrame:)); |
|
993 cache->didStartProvisionalLoadForFrameFunc = getMethod(delegate, @selector(webView:didStartProvisionalLoadForFrame:)); |
|
994 cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:)); |
|
995 cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:)); |
|
996 cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:)); |
|
997 } |
|
998 |
|
999 WebFrameLoadDelegateImplementationCache WebViewGetFrameLoadDelegateImplementations(WebView *webView) |
|
1000 { |
|
1001 return webView->_private->frameLoadDelegateImplementations; |
|
1002 } |
|
1003 |
|
1004 - (id)_policyDelegateForwarder |
|
1005 { |
|
1006 if (!_private->policyDelegateForwarder) |
|
1007 _private->policyDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->policyDelegate defaultTarget:[WebDefaultPolicyDelegate sharedPolicyDelegate] catchExceptions:_private->catchesDelegateExceptions]; |
|
1008 return _private->policyDelegateForwarder; |
|
1009 } |
|
1010 |
|
1011 - (id)_UIDelegateForwarder |
|
1012 { |
|
1013 if (!_private->UIDelegateForwarder) |
|
1014 _private->UIDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->UIDelegate defaultTarget:[WebDefaultUIDelegate sharedUIDelegate] catchExceptions:_private->catchesDelegateExceptions]; |
|
1015 return _private->UIDelegateForwarder; |
|
1016 } |
|
1017 |
|
1018 - (id)_editingDelegateForwarder |
|
1019 { |
|
1020 // This can be called during window deallocation by QTMovieView in the QuickTime Cocoa Plug-in. |
|
1021 // Not sure if that is a bug or not. |
|
1022 if (!_private) |
|
1023 return nil; |
|
1024 |
|
1025 if (!_private->editingDelegateForwarder) |
|
1026 _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->editingDelegate defaultTarget:[WebDefaultEditingDelegate sharedEditingDelegate] catchExceptions:_private->catchesDelegateExceptions]; |
|
1027 return _private->editingDelegateForwarder; |
|
1028 } |
|
1029 |
|
1030 - (id)_scriptDebugDelegateForwarder |
|
1031 { |
|
1032 if (!_private->scriptDebugDelegateForwarder) |
|
1033 _private->scriptDebugDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget:_private->scriptDebugDelegate defaultTarget:[WebDefaultScriptDebugDelegate sharedScriptDebugDelegate] catchExceptions:_private->catchesDelegateExceptions]; |
|
1034 return _private->scriptDebugDelegateForwarder; |
|
1035 } |
|
1036 |
|
1037 - (void)_closeWindow |
|
1038 { |
|
1039 [[self _UIDelegateForwarder] webViewClose:self]; |
|
1040 } |
|
1041 |
|
1042 + (void)_unregisterViewClassAndRepresentationClassForMIMEType:(NSString *)MIMEType; |
|
1043 { |
|
1044 [[WebFrameView _viewTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; |
|
1045 [[WebDataSource _repTypesAllowImageTypeOmission:NO] removeObjectForKey:MIMEType]; |
|
1046 |
|
1047 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) |
|
1048 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner |
|
1049 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness |
|
1050 MIMETypeRegistry::getSupportedNonImageMIMETypes().remove(MIMEType); |
|
1051 } |
|
1052 |
|
1053 + (void)_registerViewClass:(Class)viewClass representationClass:(Class)representationClass forURLScheme:(NSString *)URLScheme; |
|
1054 { |
|
1055 NSString *MIMEType = [self _generatedMIMETypeForURLScheme:URLScheme]; |
|
1056 [self registerViewClass:viewClass representationClass:representationClass forMIMEType:MIMEType]; |
|
1057 |
|
1058 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) |
|
1059 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner |
|
1060 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness |
|
1061 if ([viewClass class] == [WebHTMLView class]) |
|
1062 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType); |
|
1063 |
|
1064 // This is used to make _representationExistsForURLScheme faster. |
|
1065 // Without this set, we'd have to create the MIME type each time. |
|
1066 if (schemesWithRepresentationsSet == nil) { |
|
1067 schemesWithRepresentationsSet = [[NSMutableSet alloc] init]; |
|
1068 } |
|
1069 [schemesWithRepresentationsSet addObject:[[[URLScheme lowercaseString] copy] autorelease]]; |
|
1070 } |
|
1071 |
|
1072 + (NSString *)_generatedMIMETypeForURLScheme:(NSString *)URLScheme |
|
1073 { |
|
1074 return [@"x-apple-web-kit/" stringByAppendingString:[URLScheme lowercaseString]]; |
|
1075 } |
|
1076 |
|
1077 + (BOOL)_representationExistsForURLScheme:(NSString *)URLScheme |
|
1078 { |
|
1079 return [schemesWithRepresentationsSet containsObject:[URLScheme lowercaseString]]; |
|
1080 } |
|
1081 |
|
1082 + (BOOL)_canHandleRequest:(NSURLRequest *)request |
|
1083 { |
|
1084 // FIXME: If <rdar://problem/5217309> gets fixed, this check can be removed |
|
1085 if (!request) |
|
1086 return NO; |
|
1087 |
|
1088 if ([NSURLConnection canHandleRequest:request]) |
|
1089 return YES; |
|
1090 |
|
1091 NSString *scheme = [[request URL] scheme]; |
|
1092 |
|
1093 if ([self _representationExistsForURLScheme:scheme]) |
|
1094 return YES; |
|
1095 |
|
1096 return ([scheme _webkit_isCaseInsensitiveEqualToString:@"applewebdata"]); |
|
1097 } |
|
1098 |
|
1099 + (NSString *)_decodeData:(NSData *)data |
|
1100 { |
|
1101 HTMLNames::init(); // this method is used for importing bookmarks at startup, so HTMLNames are likely to be uninitialized yet |
|
1102 RefPtr<TextResourceDecoder> decoder = new TextResourceDecoder("text/html"); // bookmark files are HTML |
|
1103 String result = decoder->decode(static_cast<const char*>([data bytes]), [data length]); |
|
1104 result += decoder->flush(); |
|
1105 return result; |
|
1106 } |
|
1107 |
|
1108 - (void)_pushPerformingProgrammaticFocus |
|
1109 { |
|
1110 _private->programmaticFocusCount++; |
|
1111 } |
|
1112 |
|
1113 - (void)_popPerformingProgrammaticFocus |
|
1114 { |
|
1115 _private->programmaticFocusCount--; |
|
1116 } |
|
1117 |
|
1118 - (BOOL)_isPerformingProgrammaticFocus |
|
1119 { |
|
1120 return _private->programmaticFocusCount != 0; |
|
1121 } |
|
1122 |
|
1123 - (void)_didChangeValueForKey: (NSString *)key |
|
1124 { |
|
1125 LOG (Bindings, "calling didChangeValueForKey: %@", key); |
|
1126 [self didChangeValueForKey: key]; |
|
1127 } |
|
1128 |
|
1129 - (void)_willChangeValueForKey: (NSString *)key |
|
1130 { |
|
1131 LOG (Bindings, "calling willChangeValueForKey: %@", key); |
|
1132 [self willChangeValueForKey: key]; |
|
1133 } |
|
1134 |
|
1135 + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { |
|
1136 static NSSet *manualNotifyKeys = nil; |
|
1137 if (!manualNotifyKeys) |
|
1138 manualNotifyKeys = [[NSSet alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, |
|
1139 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil]; |
|
1140 if ([manualNotifyKeys containsObject:key]) |
|
1141 return NO; |
|
1142 return YES; |
|
1143 } |
|
1144 |
|
1145 - (NSArray *)_declaredKeys { |
|
1146 static NSArray *declaredKeys = nil; |
|
1147 if (!declaredKeys) |
|
1148 declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, |
|
1149 _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil]; |
|
1150 return declaredKeys; |
|
1151 } |
|
1152 |
|
1153 - (void)setObservationInfo:(void *)info |
|
1154 { |
|
1155 _private->observationInfo = info; |
|
1156 } |
|
1157 |
|
1158 - (void *)observationInfo |
|
1159 { |
|
1160 return _private->observationInfo; |
|
1161 } |
|
1162 |
|
1163 - (void)_willChangeBackForwardKeys |
|
1164 { |
|
1165 [self _willChangeValueForKey: _WebCanGoBackKey]; |
|
1166 [self _willChangeValueForKey: _WebCanGoForwardKey]; |
|
1167 } |
|
1168 |
|
1169 - (void)_didChangeBackForwardKeys |
|
1170 { |
|
1171 [self _didChangeValueForKey: _WebCanGoBackKey]; |
|
1172 [self _didChangeValueForKey: _WebCanGoForwardKey]; |
|
1173 } |
|
1174 |
|
1175 - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame |
|
1176 { |
|
1177 [self _willChangeBackForwardKeys]; |
|
1178 if (frame == [self mainFrame]){ |
|
1179 // Force an observer update by sending a will/did. |
|
1180 [self _willChangeValueForKey: _WebIsLoadingKey]; |
|
1181 [self _didChangeValueForKey: _WebIsLoadingKey]; |
|
1182 |
|
1183 [self _willChangeValueForKey: _WebMainFrameURLKey]; |
|
1184 } |
|
1185 |
|
1186 [NSApp setWindowsNeedUpdate:YES]; |
|
1187 } |
|
1188 |
|
1189 - (void)_didCommitLoadForFrame:(WebFrame *)frame |
|
1190 { |
|
1191 if (frame == [self mainFrame]) |
|
1192 [self _didChangeValueForKey: _WebMainFrameURLKey]; |
|
1193 [NSApp setWindowsNeedUpdate:YES]; |
|
1194 } |
|
1195 |
|
1196 - (void)_didFinishLoadForFrame:(WebFrame *)frame |
|
1197 { |
|
1198 [self _didChangeBackForwardKeys]; |
|
1199 if (frame == [self mainFrame]){ |
|
1200 // Force an observer update by sending a will/did. |
|
1201 [self _willChangeValueForKey: _WebIsLoadingKey]; |
|
1202 [self _didChangeValueForKey: _WebIsLoadingKey]; |
|
1203 } |
|
1204 [NSApp setWindowsNeedUpdate:YES]; |
|
1205 } |
|
1206 |
|
1207 - (void)_didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame |
|
1208 { |
|
1209 [self _didChangeBackForwardKeys]; |
|
1210 if (frame == [self mainFrame]){ |
|
1211 // Force an observer update by sending a will/did. |
|
1212 [self _willChangeValueForKey: _WebIsLoadingKey]; |
|
1213 [self _didChangeValueForKey: _WebIsLoadingKey]; |
|
1214 } |
|
1215 [NSApp setWindowsNeedUpdate:YES]; |
|
1216 } |
|
1217 |
|
1218 - (void)_didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame |
|
1219 { |
|
1220 [self _didChangeBackForwardKeys]; |
|
1221 if (frame == [self mainFrame]){ |
|
1222 // Force an observer update by sending a will/did. |
|
1223 [self _willChangeValueForKey: _WebIsLoadingKey]; |
|
1224 [self _didChangeValueForKey: _WebIsLoadingKey]; |
|
1225 |
|
1226 [self _didChangeValueForKey: _WebMainFrameURLKey]; |
|
1227 } |
|
1228 [NSApp setWindowsNeedUpdate:YES]; |
|
1229 } |
|
1230 |
|
1231 - (void)_reloadForPluginChanges |
|
1232 { |
|
1233 [[self mainFrame] _reloadForPluginChanges]; |
|
1234 } |
|
1235 |
|
1236 - (NSCachedURLResponse *)_cachedResponseForURL:(NSURL *)URL |
|
1237 { |
|
1238 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL]; |
|
1239 [request _web_setHTTPUserAgent:[self userAgentForURL:URL]]; |
|
1240 NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request]; |
|
1241 [request release]; |
|
1242 return cachedResponse; |
|
1243 } |
|
1244 |
|
1245 - (void)_writeImageForElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard |
|
1246 { |
|
1247 NSURL *linkURL = [element objectForKey:WebElementLinkURLKey]; |
|
1248 DOMElement *domElement = [element objectForKey:WebElementDOMNodeKey]; |
|
1249 [pasteboard _web_writeImage:(NSImage *)(domElement ? nil : [element objectForKey:WebElementImageKey]) |
|
1250 element:domElement |
|
1251 URL:linkURL ? linkURL : (NSURL *)[element objectForKey:WebElementImageURLKey] |
|
1252 title:[element objectForKey:WebElementImageAltStringKey] |
|
1253 archive:[[element objectForKey:WebElementDOMNodeKey] webArchive] |
|
1254 types:types |
|
1255 source:nil]; |
|
1256 } |
|
1257 |
|
1258 - (void)_writeLinkElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard |
|
1259 { |
|
1260 [pasteboard _web_writeURL:[element objectForKey:WebElementLinkURLKey] |
|
1261 andTitle:[element objectForKey:WebElementLinkLabelKey] |
|
1262 types:types]; |
|
1263 } |
|
1264 |
|
1265 - (void)_setInitiatedDrag:(BOOL)initiatedDrag |
|
1266 { |
|
1267 if (!_private->page) |
|
1268 return; |
|
1269 _private->page->dragController()->setDidInitiateDrag(initiatedDrag); |
|
1270 } |
|
1271 |
|
1272 #define DASHBOARD_CONTROL_LABEL @"control" |
|
1273 |
|
1274 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions from:(NSArray *)views |
|
1275 { |
|
1276 // Add scroller regions for NSScroller and KWQScrollBar |
|
1277 int i, count = [views count]; |
|
1278 |
|
1279 for (i = 0; i < count; i++) { |
|
1280 NSView *aView = [views objectAtIndex:i]; |
|
1281 |
|
1282 if ([aView isKindOfClass:[NSScroller class]] || |
|
1283 [aView isKindOfClass:NSClassFromString (@"KWQScrollBar")]) { |
|
1284 NSRect bounds = [aView bounds]; |
|
1285 NSRect adjustedBounds; |
|
1286 adjustedBounds.origin = [self convertPoint:bounds.origin fromView:aView]; |
|
1287 adjustedBounds.origin.y = [self bounds].size.height - adjustedBounds.origin.y; |
|
1288 |
|
1289 // AppKit has horrible hack of placing absent scrollers at -100,-100 |
|
1290 if (adjustedBounds.origin.y == -100) |
|
1291 continue; |
|
1292 adjustedBounds.size = bounds.size; |
|
1293 NSRect clip = [aView visibleRect]; |
|
1294 NSRect adjustedClip; |
|
1295 adjustedClip.origin = [self convertPoint:clip.origin fromView:aView]; |
|
1296 adjustedClip.origin.y = [self bounds].size.height - adjustedClip.origin.y; |
|
1297 adjustedClip.size = clip.size; |
|
1298 WebDashboardRegion *aRegion = |
|
1299 [[[WebDashboardRegion alloc] initWithRect:adjustedBounds |
|
1300 clip:adjustedClip type:WebDashboardRegionTypeScrollerRectangle] autorelease]; |
|
1301 NSMutableArray *scrollerRegions; |
|
1302 scrollerRegions = [regions objectForKey:DASHBOARD_CONTROL_LABEL]; |
|
1303 if (!scrollerRegions) { |
|
1304 scrollerRegions = [NSMutableArray array]; |
|
1305 [regions setObject:scrollerRegions forKey:DASHBOARD_CONTROL_LABEL]; |
|
1306 } |
|
1307 [scrollerRegions addObject:aRegion]; |
|
1308 } |
|
1309 [self _addScrollerDashboardRegions:regions from:[aView subviews]]; |
|
1310 } |
|
1311 } |
|
1312 |
|
1313 - (void)_addScrollerDashboardRegions:(NSMutableDictionary *)regions |
|
1314 { |
|
1315 [self _addScrollerDashboardRegions:regions from:[self subviews]]; |
|
1316 } |
|
1317 |
|
1318 - (NSDictionary *)_dashboardRegions |
|
1319 { |
|
1320 // Only return regions from main frame. |
|
1321 Frame* mainFrame = [[[self mainFrame] _bridge] _frame]; |
|
1322 if (!mainFrame) |
|
1323 return nil; |
|
1324 NSMutableDictionary *regions = mainFrame->dashboardRegionsDictionary(); |
|
1325 [self _addScrollerDashboardRegions:regions]; |
|
1326 return regions; |
|
1327 } |
|
1328 |
|
1329 - (void)_setDashboardBehavior:(WebDashboardBehavior)behavior to:(BOOL)flag |
|
1330 { |
|
1331 // FIXME: Remove this blanket assignment once Dashboard and Dashcode implement |
|
1332 // specific support for the backward compatibility mode flag. |
|
1333 if (behavior == WebDashboardBehaviorAllowWheelScrolling && flag == NO && _private->page) |
|
1334 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(true); |
|
1335 |
|
1336 switch (behavior) { |
|
1337 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: { |
|
1338 _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows = flag; |
|
1339 break; |
|
1340 } |
|
1341 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: { |
|
1342 _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns = flag; |
|
1343 break; |
|
1344 } |
|
1345 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: { |
|
1346 _private->dashboardBehaviorAlwaysAcceptsFirstMouse = flag; |
|
1347 break; |
|
1348 } |
|
1349 case WebDashboardBehaviorAllowWheelScrolling: { |
|
1350 _private->dashboardBehaviorAllowWheelScrolling = flag; |
|
1351 break; |
|
1352 } |
|
1353 case WebDashboardBehaviorUseBackwardCompatibilityMode: { |
|
1354 if (_private->page) |
|
1355 _private->page->settings()->setUsesDashboardBackwardCompatibilityMode(flag); |
|
1356 break; |
|
1357 } |
|
1358 } |
|
1359 } |
|
1360 |
|
1361 - (BOOL)_dashboardBehavior:(WebDashboardBehavior)behavior |
|
1362 { |
|
1363 switch (behavior) { |
|
1364 case WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows: { |
|
1365 return _private->dashboardBehaviorAlwaysSendMouseEventsToAllWindows; |
|
1366 } |
|
1367 case WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns: { |
|
1368 return _private->dashboardBehaviorAlwaysSendActiveNullEventsToPlugIns; |
|
1369 } |
|
1370 case WebDashboardBehaviorAlwaysAcceptsFirstMouse: { |
|
1371 return _private->dashboardBehaviorAlwaysAcceptsFirstMouse; |
|
1372 } |
|
1373 case WebDashboardBehaviorAllowWheelScrolling: { |
|
1374 return _private->dashboardBehaviorAllowWheelScrolling; |
|
1375 } |
|
1376 case WebDashboardBehaviorUseBackwardCompatibilityMode: { |
|
1377 return _private->page && _private->page->settings()->usesDashboardBackwardCompatibilityMode(); |
|
1378 } |
|
1379 } |
|
1380 return NO; |
|
1381 } |
|
1382 |
|
1383 + (void)_setShouldUseFontSmoothing:(BOOL)f |
|
1384 { |
|
1385 WebCoreSetShouldUseFontSmoothing(f); |
|
1386 } |
|
1387 |
|
1388 + (BOOL)_shouldUseFontSmoothing |
|
1389 { |
|
1390 return WebCoreShouldUseFontSmoothing(); |
|
1391 } |
|
1392 |
|
1393 + (void)_setUsesTestModeFocusRingColor:(BOOL)f |
|
1394 { |
|
1395 setUsesTestModeFocusRingColor(f); |
|
1396 } |
|
1397 |
|
1398 + (BOOL)_usesTestModeFocusRingColor |
|
1399 { |
|
1400 return usesTestModeFocusRingColor(); |
|
1401 } |
|
1402 |
|
1403 // This is only used by older versions of Safari and should be removed in a future release. |
|
1404 + (NSString *)_minimumRequiredSafariBuildNumber |
|
1405 { |
|
1406 return @"420+"; |
|
1407 } |
|
1408 |
|
1409 - (void)setAlwaysShowVerticalScroller:(BOOL)flag |
|
1410 { |
|
1411 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; |
|
1412 if (flag) { |
|
1413 [scrollview setVerticalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES]; |
|
1414 } else { |
|
1415 [scrollview setVerticalScrollingModeLocked:NO]; |
|
1416 [scrollview setVerticalScrollingMode:WebCoreScrollbarAuto]; |
|
1417 } |
|
1418 } |
|
1419 |
|
1420 - (BOOL)alwaysShowVerticalScroller |
|
1421 { |
|
1422 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; |
|
1423 return [scrollview verticalScrollingModeLocked] && [scrollview verticalScrollingMode] == WebCoreScrollbarAlwaysOn; |
|
1424 } |
|
1425 |
|
1426 - (void)setAlwaysShowHorizontalScroller:(BOOL)flag |
|
1427 { |
|
1428 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; |
|
1429 if (flag) { |
|
1430 [scrollview setHorizontalScrollingMode:WebCoreScrollbarAlwaysOn andLock:YES]; |
|
1431 } else { |
|
1432 [scrollview setHorizontalScrollingModeLocked:NO]; |
|
1433 [scrollview setHorizontalScrollingMode:WebCoreScrollbarAuto]; |
|
1434 } |
|
1435 } |
|
1436 |
|
1437 - (void)setProhibitsMainFrameScrolling:(BOOL)prohibits |
|
1438 { |
|
1439 Frame* mainFrame = [[[self mainFrame] _bridge] _frame]; |
|
1440 if (mainFrame) |
|
1441 mainFrame->setProhibitsScrolling(prohibits); |
|
1442 } |
|
1443 |
|
1444 - (BOOL)alwaysShowHorizontalScroller |
|
1445 { |
|
1446 WebDynamicScrollBarsView *scrollview = [[[self mainFrame] frameView] _scrollView]; |
|
1447 return [scrollview horizontalScrollingModeLocked] && [scrollview horizontalScrollingMode] == WebCoreScrollbarAlwaysOn; |
|
1448 } |
|
1449 |
|
1450 - (void)_setInViewSourceMode:(BOOL)flag |
|
1451 { |
|
1452 Frame* mainFrame = [[[self mainFrame] _bridge] _frame]; |
|
1453 if (mainFrame) |
|
1454 mainFrame->setInViewSourceMode(flag); |
|
1455 } |
|
1456 |
|
1457 - (BOOL)_inViewSourceMode |
|
1458 { |
|
1459 Frame* mainFrame = [[[self mainFrame] _bridge] _frame]; |
|
1460 return mainFrame && mainFrame->inViewSourceMode(); |
|
1461 } |
|
1462 |
|
1463 - (void)_setUseFastImageScalingMode:(BOOL)flag |
|
1464 { |
|
1465 if (_private->page && _private->page->inLowQualityImageInterpolationMode() != flag) { |
|
1466 _private->page->setInLowQualityImageInterpolationMode(flag); |
|
1467 [self setNeedsDisplay:YES]; |
|
1468 } |
|
1469 } |
|
1470 |
|
1471 - (BOOL)_inFastImageScalingMode |
|
1472 { |
|
1473 if (_private->page) |
|
1474 return _private->page->inLowQualityImageInterpolationMode(); |
|
1475 return NO; |
|
1476 } |
|
1477 |
|
1478 - (void)_setAdditionalWebPlugInPaths:(NSArray *)newPaths |
|
1479 { |
|
1480 if (!_private->pluginDatabase) |
|
1481 _private->pluginDatabase = [[WebPluginDatabase alloc] init]; |
|
1482 |
|
1483 [_private->pluginDatabase setPlugInPaths:newPaths]; |
|
1484 [_private->pluginDatabase refresh]; |
|
1485 } |
|
1486 |
|
1487 - (void)_attachScriptDebuggerToAllFrames |
|
1488 { |
|
1489 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext()) |
|
1490 [kit(frame) _attachScriptDebugger]; |
|
1491 } |
|
1492 |
|
1493 - (void)_detachScriptDebuggerFromAllFrames |
|
1494 { |
|
1495 for (Frame* frame = core([self mainFrame]); frame; frame = frame->tree()->traverseNext()) |
|
1496 [kit(frame) _detachScriptDebugger]; |
|
1497 } |
|
1498 |
|
1499 - (void)setBackgroundColor:(NSColor *)backgroundColor |
|
1500 { |
|
1501 if ([_private->backgroundColor isEqual:backgroundColor]) |
|
1502 return; |
|
1503 |
|
1504 id old = _private->backgroundColor; |
|
1505 _private->backgroundColor = [backgroundColor retain]; |
|
1506 [old release]; |
|
1507 |
|
1508 [[self mainFrame] _updateBackground]; |
|
1509 } |
|
1510 |
|
1511 - (NSColor *)backgroundColor |
|
1512 { |
|
1513 return _private->backgroundColor; |
|
1514 } |
|
1515 |
|
1516 - (BOOL)defersCallbacks |
|
1517 { |
|
1518 if (!_private->page) |
|
1519 return NO; |
|
1520 return _private->page->defersLoading(); |
|
1521 } |
|
1522 |
|
1523 - (void)setDefersCallbacks:(BOOL)defer |
|
1524 { |
|
1525 if (!_private->page) |
|
1526 return; |
|
1527 return _private->page->setDefersLoading(defer); |
|
1528 } |
|
1529 |
|
1530 // For backwards compatibility with the WebBackForwardList API, we honor both |
|
1531 // a per-WebView and a per-preferences setting for whether to use the page cache. |
|
1532 |
|
1533 - (BOOL)usesPageCache |
|
1534 { |
|
1535 return _private->usesPageCache && [[self preferences] usesPageCache]; |
|
1536 } |
|
1537 |
|
1538 - (void)setUsesPageCache:(BOOL)usesPageCache |
|
1539 { |
|
1540 _private->usesPageCache = usesPageCache; |
|
1541 |
|
1542 // Post a notification so the WebCore settings update. |
|
1543 [[self preferences] _postPreferencesChangesNotification]; |
|
1544 } |
|
1545 |
|
1546 - (void)handleAuthenticationForResource:(id)identifier challenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource |
|
1547 { |
|
1548 NSWindow *window = [self hostWindow] ? [self hostWindow] : [self window]; |
|
1549 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:challenge window:window]; |
|
1550 } |
|
1551 |
|
1552 - (void)_clearUndoRedoOperations |
|
1553 { |
|
1554 if (!_private->page) |
|
1555 return; |
|
1556 _private->page->clearUndoRedoOperations(); |
|
1557 } |
|
1558 |
|
1559 - (void)_setCatchesDelegateExceptions:(BOOL)f |
|
1560 { |
|
1561 _private->catchesDelegateExceptions = f; |
|
1562 } |
|
1563 |
|
1564 - (BOOL)_catchesDelegateExceptions |
|
1565 { |
|
1566 return _private->catchesDelegateExceptions; |
|
1567 } |
|
1568 |
|
1569 @end |
|
1570 |
|
1571 @implementation _WebSafeForwarder |
|
1572 |
|
1573 // Used to send messages to delegates that implement informal protocols. |
|
1574 |
|
1575 - (id)initWithTarget:(id)t defaultTarget:(id)dt catchExceptions:(BOOL)c |
|
1576 { |
|
1577 self = [super init]; |
|
1578 if (!self) |
|
1579 return nil; |
|
1580 target = t; // Non retained. |
|
1581 defaultTarget = dt; |
|
1582 catchExceptions = c; |
|
1583 return self; |
|
1584 } |
|
1585 |
|
1586 - (void)forwardInvocation:(NSInvocation *)invocation |
|
1587 { |
|
1588 if ([target respondsToSelector:[invocation selector]]) { |
|
1589 if (catchExceptions) { |
|
1590 @try { |
|
1591 [invocation invokeWithTarget:target]; |
|
1592 } @catch(id exception) { |
|
1593 ReportDiscardedDelegateException([invocation selector], exception); |
|
1594 } |
|
1595 } else |
|
1596 [invocation invokeWithTarget:target]; |
|
1597 return; |
|
1598 } |
|
1599 |
|
1600 if ([defaultTarget respondsToSelector:[invocation selector]]) |
|
1601 [invocation invokeWithTarget:defaultTarget]; |
|
1602 |
|
1603 // Do nothing quietly if method not implemented. |
|
1604 } |
|
1605 |
|
1606 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector |
|
1607 { |
|
1608 return [defaultTarget methodSignatureForSelector:aSelector]; |
|
1609 } |
|
1610 |
|
1611 @end |
|
1612 |
|
1613 @implementation WebView |
|
1614 |
|
1615 + (void)initialize |
|
1616 { |
|
1617 static BOOL initialized = NO; |
|
1618 if (initialized) |
|
1619 return; |
|
1620 initialized = YES; |
|
1621 |
|
1622 #ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM |
|
1623 // This prevents open source users from crashing when using the Show DOM Tree menu item in Safari 2. |
|
1624 // FIXME: remove this when we no longer need to support Safari 2. |
|
1625 if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"] && [[NSUserDefaults standardUserDefaults] boolForKey:@"IncludeDebugMenu"]) |
|
1626 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_finishedLaunching) name:NSApplicationDidFinishLaunchingNotification object:NSApp]; |
|
1627 #endif |
|
1628 |
|
1629 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillTerminate) name:NSApplicationWillTerminateNotification object:NSApp]; |
|
1630 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) name:WebPreferencesChangedNotification object:nil]; |
|
1631 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesRemovedNotification:) name:WebPreferencesRemovedNotification object:nil]; |
|
1632 } |
|
1633 |
|
1634 + (void)_applicationWillTerminate |
|
1635 { |
|
1636 applicationIsTerminating = YES; |
|
1637 if (!pluginDatabaseClientCount) |
|
1638 [WebPluginDatabase closeSharedDatabase]; |
|
1639 } |
|
1640 |
|
1641 #ifdef REMOVE_SAFARI_DOM_TREE_DEBUG_ITEM |
|
1642 // FIXME: remove this when it is no longer needed to prevent Safari from crashing |
|
1643 + (void)_finishedLaunching |
|
1644 { |
|
1645 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_removeDOMTreeMenuItem:) name:NSMenuDidAddItemNotification object:[NSApp mainMenu]]; |
|
1646 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:NSApp]; |
|
1647 } |
|
1648 |
|
1649 +(void)_removeDOMTreeMenuItem:(NSNotification *)notification |
|
1650 { |
|
1651 NSMenu *debugMenu = [[[[NSApp mainMenu] itemArray] lastObject] submenu]; |
|
1652 NSMenuItem *domTree = [debugMenu itemWithTitle:@"Show DOM Tree"]; |
|
1653 if (domTree) |
|
1654 [debugMenu removeItem:domTree]; |
|
1655 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMenuDidAddItemNotification object:[NSApp mainMenu]]; |
|
1656 } |
|
1657 #endif |
|
1658 |
|
1659 + (BOOL)canShowMIMEType:(NSString *)MIMEType |
|
1660 { |
|
1661 return [self _viewClass:nil andRepresentationClass:nil forMIMEType:MIMEType]; |
|
1662 } |
|
1663 |
|
1664 - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType |
|
1665 { |
|
1666 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForMIMEType:MIMEType]; |
|
1667 if (pluginPackage) |
|
1668 return pluginPackage; |
|
1669 |
|
1670 if (_private->pluginDatabase) |
|
1671 return [_private->pluginDatabase pluginForMIMEType:MIMEType]; |
|
1672 |
|
1673 return nil; |
|
1674 } |
|
1675 |
|
1676 - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension |
|
1677 { |
|
1678 WebBasePluginPackage *pluginPackage = [[WebPluginDatabase sharedDatabase] pluginForExtension:extension]; |
|
1679 if (pluginPackage) |
|
1680 return pluginPackage; |
|
1681 |
|
1682 if (_private->pluginDatabase) |
|
1683 return [_private->pluginDatabase pluginForExtension:extension]; |
|
1684 |
|
1685 return nil; |
|
1686 } |
|
1687 |
|
1688 - (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType |
|
1689 { |
|
1690 if ([[WebPluginDatabase sharedDatabase] isMIMETypeRegistered:MIMEType]) |
|
1691 return YES; |
|
1692 |
|
1693 if (_private->pluginDatabase && [_private->pluginDatabase isMIMETypeRegistered:MIMEType]) |
|
1694 return YES; |
|
1695 |
|
1696 return NO; |
|
1697 } |
|
1698 |
|
1699 + (BOOL)canShowMIMETypeAsHTML:(NSString *)MIMEType |
|
1700 { |
|
1701 return [WebFrameView _canShowMIMETypeAsHTML:MIMEType]; |
|
1702 } |
|
1703 |
|
1704 + (NSArray *)MIMETypesShownAsHTML |
|
1705 { |
|
1706 NSMutableDictionary *viewTypes = [WebFrameView _viewTypesAllowImageTypeOmission:YES]; |
|
1707 NSEnumerator *enumerator = [viewTypes keyEnumerator]; |
|
1708 id key; |
|
1709 NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; |
|
1710 |
|
1711 while ((key = [enumerator nextObject])) { |
|
1712 if ([viewTypes objectForKey:key] == [WebHTMLView class]) |
|
1713 [array addObject:key]; |
|
1714 } |
|
1715 |
|
1716 return array; |
|
1717 } |
|
1718 |
|
1719 + (void)setMIMETypesShownAsHTML:(NSArray *)MIMETypes |
|
1720 { |
|
1721 NSDictionary *viewTypes = [[WebFrameView _viewTypesAllowImageTypeOmission:YES] copy]; |
|
1722 NSEnumerator *enumerator = [viewTypes keyEnumerator]; |
|
1723 id key; |
|
1724 while ((key = [enumerator nextObject])) { |
|
1725 if ([viewTypes objectForKey:key] == [WebHTMLView class]) |
|
1726 [WebView _unregisterViewClassAndRepresentationClassForMIMEType:key]; |
|
1727 } |
|
1728 |
|
1729 int i, count = [MIMETypes count]; |
|
1730 for (i = 0; i < count; i++) { |
|
1731 [WebView registerViewClass:[WebHTMLView class] |
|
1732 representationClass:[WebHTMLRepresentation class] |
|
1733 forMIMEType:[MIMETypes objectAtIndex:i]]; |
|
1734 } |
|
1735 [viewTypes release]; |
|
1736 } |
|
1737 |
|
1738 + (NSURL *)URLFromPasteboard:(NSPasteboard *)pasteboard |
|
1739 { |
|
1740 return [pasteboard _web_bestURL]; |
|
1741 } |
|
1742 |
|
1743 + (NSString *)URLTitleFromPasteboard:(NSPasteboard *)pasteboard |
|
1744 { |
|
1745 return [pasteboard stringForType:WebURLNamePboardType]; |
|
1746 } |
|
1747 |
|
1748 + (void)registerURLSchemeAsLocal:(NSString *)protocol |
|
1749 { |
|
1750 FrameLoader::registerURLSchemeAsLocal(protocol); |
|
1751 } |
|
1752 |
|
1753 - (void)_registerDraggedTypes |
|
1754 { |
|
1755 NSArray *editableTypes = [WebHTMLView _insertablePasteboardTypes]; |
|
1756 NSArray *URLTypes = [NSPasteboard _web_dragTypesForURL]; |
|
1757 NSMutableSet *types = [[NSMutableSet alloc] initWithArray:editableTypes]; |
|
1758 [types addObjectsFromArray:URLTypes]; |
|
1759 [self registerForDraggedTypes:[types allObjects]]; |
|
1760 [types release]; |
|
1761 } |
|
1762 |
|
1763 - (void)_commonInitializationWithFrameName:(NSString *)frameName groupName:(NSString *)groupName |
|
1764 { |
|
1765 WebPreferences *standardPreferences = [WebPreferences standardPreferences]; |
|
1766 [standardPreferences willAddToWebView]; |
|
1767 |
|
1768 _private->preferences = [standardPreferences retain]; |
|
1769 _private->catchesDelegateExceptions = YES; |
|
1770 _private->mainFrameDocumentReady = NO; |
|
1771 _private->drawsBackground = YES; |
|
1772 _private->smartInsertDeleteEnabled = YES; |
|
1773 _private->backgroundColor = [[NSColor whiteColor] retain]; |
|
1774 |
|
1775 NSRect f = [self frame]; |
|
1776 WebFrameView *frameView = [[WebFrameView alloc] initWithFrame: NSMakeRect(0,0,f.size.width,f.size.height)]; |
|
1777 [frameView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; |
|
1778 [self addSubview:frameView]; |
|
1779 [frameView release]; |
|
1780 |
|
1781 WebKitInitializeLoggingChannelsIfNecessary(); |
|
1782 WebCore::InitializeLoggingChannelsIfNecessary(); |
|
1783 [WebHistoryItem initWindowWatcherIfNecessary]; |
|
1784 |
|
1785 _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self)); |
|
1786 [[[WebFrameBridge alloc] initMainFrameWithPage:_private->page frameName:frameName frameView:frameView] release]; |
|
1787 |
|
1788 [self _addToAllWebViewsSet]; |
|
1789 [self setGroupName:groupName]; |
|
1790 |
|
1791 // If there's already a next key view (e.g., from a nib), wire it up to our |
|
1792 // contained frame view. In any case, wire our next key view up to the our |
|
1793 // contained frame view. This works together with our becomeFirstResponder |
|
1794 // and setNextKeyView overrides. |
|
1795 NSView *nextKeyView = [self nextKeyView]; |
|
1796 if (nextKeyView != nil && nextKeyView != frameView) { |
|
1797 [frameView setNextKeyView:nextKeyView]; |
|
1798 } |
|
1799 [super setNextKeyView:frameView]; |
|
1800 |
|
1801 ++WebViewCount; |
|
1802 |
|
1803 [self _registerDraggedTypes]; |
|
1804 |
|
1805 // initialize WebScriptDebugServer here so listeners can register before any pages are loaded. |
|
1806 if ([WebView _scriptDebuggerEnabled]) |
|
1807 [WebScriptDebugServer sharedScriptDebugServer]; |
|
1808 |
|
1809 WebPreferences *prefs = [self preferences]; |
|
1810 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) |
|
1811 name:WebPreferencesChangedNotification object:prefs]; |
|
1812 |
|
1813 // Post a notification so the WebCore settings update. |
|
1814 [[self preferences] _postPreferencesChangesNotification]; |
|
1815 |
|
1816 if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) |
|
1817 FrameLoader::setRestrictAccessToLocal(true); |
|
1818 } |
|
1819 |
|
1820 - (id)initWithFrame:(NSRect)f |
|
1821 { |
|
1822 return [self initWithFrame:f frameName:nil groupName:nil]; |
|
1823 } |
|
1824 |
|
1825 - (id)initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName; |
|
1826 { |
|
1827 self = [super initWithFrame:f]; |
|
1828 if (!self) |
|
1829 return nil; |
|
1830 |
|
1831 #ifdef ENABLE_WEBKIT_UNSET_DYLD_FRAMEWORK_PATH |
|
1832 // DYLD_FRAMEWORK_PATH is used so Safari will load the development version of WebKit, which |
|
1833 // may not work with other WebKit applications. Unsetting DYLD_FRAMEWORK_PATH removes the |
|
1834 // need for Safari to unset it to prevent it from being passed to applications it launches. |
|
1835 // Unsetting it when a WebView is first created is as good a place as any. |
|
1836 // See <http://bugs.webkit.org/show_bug.cgi?id=4286> for more details. |
|
1837 if (getenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH")) { |
|
1838 unsetenv("DYLD_FRAMEWORK_PATH"); |
|
1839 unsetenv("WEBKIT_UNSET_DYLD_FRAMEWORK_PATH"); |
|
1840 } |
|
1841 #endif |
|
1842 |
|
1843 _private = [[WebViewPrivate alloc] init]; |
|
1844 [self _commonInitializationWithFrameName:frameName groupName:groupName]; |
|
1845 [self setMaintainsBackForwardList: YES]; |
|
1846 return self; |
|
1847 } |
|
1848 |
|
1849 - (id)initWithCoder:(NSCoder *)decoder |
|
1850 { |
|
1851 WebView *result = nil; |
|
1852 |
|
1853 NS_DURING |
|
1854 |
|
1855 NSString *frameName; |
|
1856 NSString *groupName; |
|
1857 WebPreferences *preferences; |
|
1858 BOOL useBackForwardList = NO; |
|
1859 BOOL allowsUndo = YES; |
|
1860 |
|
1861 result = [super initWithCoder:decoder]; |
|
1862 result->_private = [[WebViewPrivate alloc] init]; |
|
1863 |
|
1864 // We don't want any of the archived subviews. The subviews will always |
|
1865 // be created in _commonInitializationFrameName:groupName:. |
|
1866 [[result subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; |
|
1867 |
|
1868 if ([decoder allowsKeyedCoding]) { |
|
1869 frameName = [decoder decodeObjectForKey:@"FrameName"]; |
|
1870 groupName = [decoder decodeObjectForKey:@"GroupName"]; |
|
1871 preferences = [decoder decodeObjectForKey:@"Preferences"]; |
|
1872 useBackForwardList = [decoder decodeBoolForKey:@"UseBackForwardList"]; |
|
1873 if ([decoder containsValueForKey:@"AllowsUndo"]) |
|
1874 allowsUndo = [decoder decodeBoolForKey:@"AllowsUndo"]; |
|
1875 } else { |
|
1876 int version; |
|
1877 [decoder decodeValueOfObjCType:@encode(int) at:&version]; |
|
1878 frameName = [decoder decodeObject]; |
|
1879 groupName = [decoder decodeObject]; |
|
1880 preferences = [decoder decodeObject]; |
|
1881 if (version > 1) |
|
1882 [decoder decodeValuesOfObjCTypes:"c", &useBackForwardList]; |
|
1883 // The allowsUndo field is no longer written out in encodeWithCoder, but since there are |
|
1884 // version 3 NIBs that have this field encoded, we still need to read it in. |
|
1885 if (version == 3) |
|
1886 [decoder decodeValuesOfObjCTypes:"c", &allowsUndo]; |
|
1887 } |
|
1888 |
|
1889 if (![frameName isKindOfClass:[NSString class]]) |
|
1890 frameName = nil; |
|
1891 if (![groupName isKindOfClass:[NSString class]]) |
|
1892 groupName = nil; |
|
1893 if (![preferences isKindOfClass:[WebPreferences class]]) |
|
1894 preferences = nil; |
|
1895 |
|
1896 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", frameName, groupName, (int)useBackForwardList); |
|
1897 [result _commonInitializationWithFrameName:frameName groupName:groupName]; |
|
1898 [result page]->backForwardList()->setEnabled(useBackForwardList); |
|
1899 result->_private->allowsUndo = allowsUndo; |
|
1900 if (preferences) |
|
1901 [result setPreferences:preferences]; |
|
1902 |
|
1903 NS_HANDLER |
|
1904 |
|
1905 result = nil; |
|
1906 [self release]; |
|
1907 |
|
1908 NS_ENDHANDLER |
|
1909 |
|
1910 return result; |
|
1911 } |
|
1912 |
|
1913 - (void)encodeWithCoder:(NSCoder *)encoder |
|
1914 { |
|
1915 // Set asside the subviews before we archive. We don't want to archive any subviews. |
|
1916 // The subviews will always be created in _commonInitializationFrameName:groupName:. |
|
1917 id originalSubviews = _subviews; |
|
1918 _subviews = nil; |
|
1919 |
|
1920 [super encodeWithCoder:encoder]; |
|
1921 |
|
1922 // Restore the subviews we set aside. |
|
1923 _subviews = originalSubviews; |
|
1924 |
|
1925 BOOL useBackForwardList = _private->page && _private->page->backForwardList()->enabled(); |
|
1926 if ([encoder allowsKeyedCoding]) { |
|
1927 [encoder encodeObject:[[self mainFrame] name] forKey:@"FrameName"]; |
|
1928 [encoder encodeObject:[self groupName] forKey:@"GroupName"]; |
|
1929 [encoder encodeObject:[self preferences] forKey:@"Preferences"]; |
|
1930 [encoder encodeBool:useBackForwardList forKey:@"UseBackForwardList"]; |
|
1931 [encoder encodeBool:_private->allowsUndo forKey:@"AllowsUndo"]; |
|
1932 } else { |
|
1933 int version = WebViewVersion; |
|
1934 [encoder encodeValueOfObjCType:@encode(int) at:&version]; |
|
1935 [encoder encodeObject:[[self mainFrame] name]]; |
|
1936 [encoder encodeObject:[self groupName]]; |
|
1937 [encoder encodeObject:[self preferences]]; |
|
1938 [encoder encodeValuesOfObjCTypes:"c", &useBackForwardList]; |
|
1939 // DO NOT encode any new fields here, doing so will break older WebKit releases. |
|
1940 } |
|
1941 |
|
1942 LOG(Encoding, "FrameName = %@, GroupName = %@, useBackForwardList = %d\n", [[self mainFrame] name], [self groupName], (int)useBackForwardList); |
|
1943 } |
|
1944 |
|
1945 - (void)dealloc |
|
1946 { |
|
1947 // call close to ensure we tear-down completely |
|
1948 // this maintains our old behavior for existing applications |
|
1949 [self _close]; |
|
1950 |
|
1951 --WebViewCount; |
|
1952 |
|
1953 [_private release]; |
|
1954 // [super dealloc] can end up dispatching against _private (3466082) |
|
1955 _private = nil; |
|
1956 |
|
1957 [super dealloc]; |
|
1958 } |
|
1959 |
|
1960 - (void)finalize |
|
1961 { |
|
1962 ASSERT(_private->closed); |
|
1963 |
|
1964 --WebViewCount; |
|
1965 |
|
1966 [super finalize]; |
|
1967 } |
|
1968 |
|
1969 - (void)close |
|
1970 { |
|
1971 [self _close]; |
|
1972 } |
|
1973 |
|
1974 - (void)setShouldCloseWithWindow:(BOOL)close |
|
1975 { |
|
1976 _private->shouldCloseWithWindow = close; |
|
1977 } |
|
1978 |
|
1979 - (BOOL)shouldCloseWithWindow |
|
1980 { |
|
1981 return _private->shouldCloseWithWindow; |
|
1982 } |
|
1983 |
|
1984 - (void)viewWillMoveToWindow:(NSWindow *)window |
|
1985 { |
|
1986 // Don't do anything if we aren't initialized. This happens when decoding a WebView. |
|
1987 if (!_private) |
|
1988 return; |
|
1989 |
|
1990 if ([self window]) |
|
1991 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:[self window]]; |
|
1992 |
|
1993 if (window) { |
|
1994 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:window]; |
|
1995 |
|
1996 // Ensure that we will receive the events that WebHTMLView (at least) needs. It's expensive enough |
|
1997 // that we don't want to call it over and over. |
|
1998 [window setAcceptsMouseMovedEvents:YES]; |
|
1999 WKSetNSWindowShouldPostEventNotifications(window, YES); |
|
2000 } |
|
2001 } |
|
2002 |
|
2003 - (void)_windowWillClose:(NSNotification *)notification |
|
2004 { |
|
2005 if ([self shouldCloseWithWindow] && ([self window] == [self hostWindow] || ([self window] && ![self hostWindow]) || (![self window] && [self hostWindow]))) |
|
2006 [self _close]; |
|
2007 } |
|
2008 |
|
2009 - (void)setPreferences:(WebPreferences *)prefs |
|
2010 { |
|
2011 if (!prefs) |
|
2012 prefs = [WebPreferences standardPreferences]; |
|
2013 |
|
2014 if (_private->preferences == prefs) |
|
2015 return; |
|
2016 |
|
2017 [prefs willAddToWebView]; |
|
2018 |
|
2019 WebPreferences *oldPrefs = _private->preferences; |
|
2020 |
|
2021 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:[self preferences]]; |
|
2022 [WebPreferences _removeReferenceForIdentifier:[oldPrefs identifier]]; |
|
2023 |
|
2024 _private->preferences = [prefs retain]; |
|
2025 |
|
2026 // After registering for the notification, post it so the WebCore settings update. |
|
2027 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_preferencesChangedNotification:) |
|
2028 name:WebPreferencesChangedNotification object:[self preferences]]; |
|
2029 [[self preferences] _postPreferencesChangesNotification]; |
|
2030 |
|
2031 [oldPrefs didRemoveFromWebView]; |
|
2032 [oldPrefs release]; |
|
2033 } |
|
2034 |
|
2035 - (WebPreferences *)preferences |
|
2036 { |
|
2037 return _private->preferences; |
|
2038 } |
|
2039 |
|
2040 - (void)setPreferencesIdentifier:(NSString *)anIdentifier |
|
2041 { |
|
2042 if (!_private->closed && ![anIdentifier isEqual:[[self preferences] identifier]]) { |
|
2043 WebPreferences *prefs = [[WebPreferences alloc] initWithIdentifier:anIdentifier]; |
|
2044 [self setPreferences:prefs]; |
|
2045 [prefs release]; |
|
2046 } |
|
2047 } |
|
2048 |
|
2049 - (NSString *)preferencesIdentifier |
|
2050 { |
|
2051 return [[self preferences] identifier]; |
|
2052 } |
|
2053 |
|
2054 |
|
2055 - (void)setUIDelegate:delegate |
|
2056 { |
|
2057 _private->UIDelegate = delegate; |
|
2058 [_private->UIDelegateForwarder release]; |
|
2059 _private->UIDelegateForwarder = nil; |
|
2060 } |
|
2061 |
|
2062 - UIDelegate |
|
2063 { |
|
2064 return _private->UIDelegate; |
|
2065 } |
|
2066 |
|
2067 - (void)setResourceLoadDelegate: delegate |
|
2068 { |
|
2069 _private->resourceProgressDelegate = delegate; |
|
2070 [self _cacheResourceLoadDelegateImplementations]; |
|
2071 } |
|
2072 |
|
2073 - resourceLoadDelegate |
|
2074 { |
|
2075 return _private->resourceProgressDelegate; |
|
2076 } |
|
2077 |
|
2078 - (void)setDownloadDelegate: delegate |
|
2079 { |
|
2080 _private->downloadDelegate = delegate; |
|
2081 } |
|
2082 |
|
2083 |
|
2084 - downloadDelegate |
|
2085 { |
|
2086 return _private->downloadDelegate; |
|
2087 } |
|
2088 |
|
2089 - (void)setPolicyDelegate:delegate |
|
2090 { |
|
2091 _private->policyDelegate = delegate; |
|
2092 [_private->policyDelegateForwarder release]; |
|
2093 _private->policyDelegateForwarder = nil; |
|
2094 } |
|
2095 |
|
2096 - policyDelegate |
|
2097 { |
|
2098 return _private->policyDelegate; |
|
2099 } |
|
2100 |
|
2101 - (void)setFrameLoadDelegate:delegate |
|
2102 { |
|
2103 _private->frameLoadDelegate = delegate; |
|
2104 [self _cacheFrameLoadDelegateImplementations]; |
|
2105 } |
|
2106 |
|
2107 - frameLoadDelegate |
|
2108 { |
|
2109 return _private->frameLoadDelegate; |
|
2110 } |
|
2111 |
|
2112 - (WebFrame *)mainFrame |
|
2113 { |
|
2114 // This can be called in initialization, before _private has been set up (3465613) |
|
2115 if (!_private) |
|
2116 return nil; |
|
2117 if (!_private->page) |
|
2118 return nil; |
|
2119 return kit(_private->page->mainFrame()); |
|
2120 } |
|
2121 |
|
2122 - (WebFrame *)selectedFrame |
|
2123 { |
|
2124 // If the first responder is a view in our tree, we get the frame containing the first responder. |
|
2125 // This is faster than searching the frame hierarchy, and will give us a result even in the case |
|
2126 // where the focused frame doesn't actually contain a selection. |
|
2127 WebFrame *focusedFrame = [self _focusedFrame]; |
|
2128 if (focusedFrame) |
|
2129 return focusedFrame; |
|
2130 |
|
2131 // If the first responder is outside of our view tree, we search for a frame containing a selection. |
|
2132 // There should be at most only one of these. |
|
2133 return [[self mainFrame] _findFrameWithSelection]; |
|
2134 } |
|
2135 |
|
2136 - (WebBackForwardList *)backForwardList |
|
2137 { |
|
2138 if (!_private->page) |
|
2139 return nil; |
|
2140 if (!_private->page->backForwardList()->enabled()) |
|
2141 return nil; |
|
2142 return kit(_private->page->backForwardList()); |
|
2143 } |
|
2144 |
|
2145 - (void)setMaintainsBackForwardList: (BOOL)flag |
|
2146 { |
|
2147 if (!_private->page) |
|
2148 return; |
|
2149 _private->page->backForwardList()->setEnabled(flag); |
|
2150 } |
|
2151 |
|
2152 - (BOOL)goBack |
|
2153 { |
|
2154 if (!_private->page) |
|
2155 return NO; |
|
2156 |
|
2157 return _private->page->goBack(); |
|
2158 } |
|
2159 |
|
2160 - (BOOL)goForward |
|
2161 { |
|
2162 if (!_private->page) |
|
2163 return NO; |
|
2164 |
|
2165 return _private->page->goForward(); |
|
2166 } |
|
2167 |
|
2168 - (BOOL)goToBackForwardItem:(WebHistoryItem *)item |
|
2169 { |
|
2170 if (!_private->page) |
|
2171 return NO; |
|
2172 |
|
2173 _private->page->goToItem(core(item), FrameLoadTypeIndexedBackForward); |
|
2174 return YES; |
|
2175 } |
|
2176 |
|
2177 - (void)setTextSizeMultiplier:(float)m |
|
2178 { |
|
2179 // NOTE: This has no visible effect when viewing a PDF (see <rdar://problem/4737380>) |
|
2180 if (_private->textSizeMultiplier == m) |
|
2181 return; |
|
2182 |
|
2183 _private->textSizeMultiplier = m; |
|
2184 [self _notifyTextSizeMultiplierChanged]; |
|
2185 } |
|
2186 |
|
2187 - (float)textSizeMultiplier |
|
2188 { |
|
2189 return _private->textSizeMultiplier; |
|
2190 } |
|
2191 |
|
2192 - (void)setApplicationNameForUserAgent:(NSString *)applicationName |
|
2193 { |
|
2194 NSString *name = [applicationName copy]; |
|
2195 [_private->applicationNameForUserAgent release]; |
|
2196 _private->applicationNameForUserAgent = name; |
|
2197 if (!_private->userAgentOverridden) |
|
2198 *_private->userAgent = String(); |
|
2199 } |
|
2200 |
|
2201 - (NSString *)applicationNameForUserAgent |
|
2202 { |
|
2203 return [[_private->applicationNameForUserAgent retain] autorelease]; |
|
2204 } |
|
2205 |
|
2206 - (void)setCustomUserAgent:(NSString *)userAgentString |
|
2207 { |
|
2208 *_private->userAgent = userAgentString; |
|
2209 _private->userAgentOverridden = userAgentString != nil; |
|
2210 } |
|
2211 |
|
2212 - (NSString *)customUserAgent |
|
2213 { |
|
2214 if (!_private->userAgentOverridden) |
|
2215 return nil; |
|
2216 return *_private->userAgent; |
|
2217 } |
|
2218 |
|
2219 - (void)setMediaStyle:(NSString *)mediaStyle |
|
2220 { |
|
2221 if (_private->mediaStyle != mediaStyle) { |
|
2222 [_private->mediaStyle release]; |
|
2223 _private->mediaStyle = [mediaStyle copy]; |
|
2224 } |
|
2225 } |
|
2226 |
|
2227 - (NSString *)mediaStyle |
|
2228 { |
|
2229 return _private->mediaStyle; |
|
2230 } |
|
2231 |
|
2232 - (BOOL)supportsTextEncoding |
|
2233 { |
|
2234 id documentView = [[[self mainFrame] frameView] documentView]; |
|
2235 return [documentView conformsToProtocol:@protocol(WebDocumentText)] |
|
2236 && [documentView supportsTextEncoding]; |
|
2237 } |
|
2238 |
|
2239 - (void)setCustomTextEncodingName:(NSString *)encoding |
|
2240 { |
|
2241 NSString *oldEncoding = [self customTextEncodingName]; |
|
2242 if (encoding == oldEncoding || [encoding isEqualToString:oldEncoding]) |
|
2243 return; |
|
2244 FrameLoader* mainFrameLoader = [[self mainFrame] _frameLoader]; |
|
2245 if (mainFrameLoader) |
|
2246 mainFrameLoader->reloadAllowingStaleData(encoding); |
|
2247 } |
|
2248 |
|
2249 - (NSString *)_mainFrameOverrideEncoding |
|
2250 { |
|
2251 WebDataSource *dataSource = [[self mainFrame] provisionalDataSource]; |
|
2252 if (dataSource == nil) |
|
2253 dataSource = [[self mainFrame] _dataSource]; |
|
2254 if (dataSource == nil) |
|
2255 return nil; |
|
2256 return nsStringNilIfEmpty([dataSource _documentLoader]->overrideEncoding()); |
|
2257 } |
|
2258 |
|
2259 - (NSString *)customTextEncodingName |
|
2260 { |
|
2261 return [self _mainFrameOverrideEncoding]; |
|
2262 } |
|
2263 |
|
2264 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script |
|
2265 { |
|
2266 // FIXME: We can remove this workaround for VitalSource Bookshelf when they update |
|
2267 // their code so that it no longer calls stringByEvaluatingJavaScriptFromString with a return statement. |
|
2268 // Return statements are only valid in a function. See <rdar://problem/5095515> for the evangelism bug. |
|
2269 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_VITALSOURCE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.vitalsource.bookshelf"]) { |
|
2270 NSRange returnStringRange = [script rangeOfString:@"return "]; |
|
2271 if (returnStringRange.length != 0 && returnStringRange.location == 0) |
|
2272 script = [script substringFromIndex: returnStringRange.location + returnStringRange.length]; |
|
2273 } |
|
2274 |
|
2275 NSString *result = [[[self mainFrame] _bridge] stringByEvaluatingJavaScriptFromString:script]; |
|
2276 // The only way stringByEvaluatingJavaScriptFromString can return nil is if the frame was removed by the script |
|
2277 // Since there's no way to get rid of the main frame, result will never ever be nil here. |
|
2278 ASSERT(result); |
|
2279 |
|
2280 return result; |
|
2281 } |
|
2282 |
|
2283 - (WebScriptObject *)windowScriptObject |
|
2284 { |
|
2285 Frame* coreFrame = core([self mainFrame]); |
|
2286 if (!coreFrame) |
|
2287 return nil; |
|
2288 return coreFrame->windowScriptObject(); |
|
2289 } |
|
2290 |
|
2291 // Get the appropriate user-agent string for a particular URL. |
|
2292 - (NSString *)userAgentForURL:(NSURL *)url |
|
2293 { |
|
2294 return [self _userAgentForURL:KURL([url absoluteURL])]; |
|
2295 } |
|
2296 |
|
2297 - (void)setHostWindow:(NSWindow *)hostWindow |
|
2298 { |
|
2299 if (!_private->closed && hostWindow != _private->hostWindow) { |
|
2300 [[self mainFrame] _viewWillMoveToHostWindow:hostWindow]; |
|
2301 if (_private->hostWindow) |
|
2302 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:_private->hostWindow]; |
|
2303 if (hostWindow) |
|
2304 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowWillClose:) name:NSWindowWillCloseNotification object:hostWindow]; |
|
2305 [_private->hostWindow release]; |
|
2306 _private->hostWindow = [hostWindow retain]; |
|
2307 [[self mainFrame] _viewDidMoveToHostWindow]; |
|
2308 } |
|
2309 } |
|
2310 |
|
2311 - (NSWindow *)hostWindow |
|
2312 { |
|
2313 return _private->hostWindow; |
|
2314 } |
|
2315 |
|
2316 - (NSView <WebDocumentView> *)documentViewAtWindowPoint:(NSPoint)point |
|
2317 { |
|
2318 return [[self _frameViewAtWindowPoint:point] documentView]; |
|
2319 } |
|
2320 |
|
2321 - (NSDictionary *)_elementAtWindowPoint:(NSPoint)windowPoint |
|
2322 { |
|
2323 WebFrameView *frameView = [self _frameViewAtWindowPoint:windowPoint]; |
|
2324 if (!frameView) |
|
2325 return nil; |
|
2326 NSView <WebDocumentView> *documentView = [frameView documentView]; |
|
2327 if ([documentView conformsToProtocol:@protocol(WebDocumentElement)]) { |
|
2328 NSPoint point = [documentView convertPoint:windowPoint fromView:nil]; |
|
2329 return [(NSView <WebDocumentElement> *)documentView elementAtPoint:point]; |
|
2330 } |
|
2331 return [NSDictionary dictionaryWithObject:[frameView webFrame] forKey:WebElementFrameKey]; |
|
2332 } |
|
2333 |
|
2334 - (NSDictionary *)elementAtPoint:(NSPoint)point |
|
2335 { |
|
2336 return [self _elementAtWindowPoint:[self convertPoint:point toView:nil]]; |
|
2337 } |
|
2338 |
|
2339 // The following 2 internal NSView methods are called on the drag destination by make scrolling while dragging work. |
|
2340 // Scrolling while dragging will only work if the drag destination is in a scroll view. The WebView is the drag destination. |
|
2341 // When dragging to a WebView, the document subview should scroll, but it doesn't because it is not the drag destination. |
|
2342 // Forward these calls to the document subview to make its scroll view scroll. |
|
2343 - (void)_autoscrollForDraggingInfo:(id)draggingInfo timeDelta:(NSTimeInterval)repeatDelta |
|
2344 { |
|
2345 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; |
|
2346 [documentView _autoscrollForDraggingInfo:draggingInfo timeDelta:repeatDelta]; |
|
2347 } |
|
2348 |
|
2349 - (BOOL)_shouldAutoscrollForDraggingInfo:(id)draggingInfo |
|
2350 { |
|
2351 NSView <WebDocumentView> *documentView = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; |
|
2352 return [documentView _shouldAutoscrollForDraggingInfo:draggingInfo]; |
|
2353 } |
|
2354 |
|
2355 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo |
|
2356 { |
|
2357 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; |
|
2358 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil); |
|
2359 IntPoint client([draggingInfo draggingLocation]); |
|
2360 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); |
|
2361 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper); |
|
2362 return core(self)->dragController()->dragEntered(&dragData); |
|
2363 } |
|
2364 |
|
2365 - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo |
|
2366 { |
|
2367 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; |
|
2368 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil); |
|
2369 IntPoint client([draggingInfo draggingLocation]); |
|
2370 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); |
|
2371 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper); |
|
2372 return core(self)->dragController()->dragUpdated(&dragData); |
|
2373 } |
|
2374 |
|
2375 - (void)draggingExited:(id <NSDraggingInfo>)draggingInfo |
|
2376 { |
|
2377 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; |
|
2378 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]] ? (WebHTMLView*)view : nil); |
|
2379 IntPoint client([draggingInfo draggingLocation]); |
|
2380 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); |
|
2381 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper); |
|
2382 core(self)->dragController()->dragExited(&dragData); |
|
2383 } |
|
2384 |
|
2385 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo |
|
2386 { |
|
2387 return YES; |
|
2388 } |
|
2389 |
|
2390 - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo |
|
2391 { |
|
2392 NSView <WebDocumentView>* view = [self documentViewAtWindowPoint:[draggingInfo draggingLocation]]; |
|
2393 WebPasteboardHelper helper([view isKindOfClass:[WebHTMLView class]]? (WebHTMLView*)view : nil); |
|
2394 IntPoint client([draggingInfo draggingLocation]); |
|
2395 IntPoint global(globalPoint([draggingInfo draggingLocation], [self window])); |
|
2396 DragData dragData(draggingInfo, client, global, (DragOperation)[draggingInfo draggingSourceOperationMask], &helper); |
|
2397 return core(self)->dragController()->performDrag(&dragData); |
|
2398 } |
|
2399 |
|
2400 - (NSView *)_hitTest:(NSPoint *)aPoint dragTypes:(NSSet *)types |
|
2401 { |
|
2402 NSView *hitView = [super _hitTest:aPoint dragTypes:types]; |
|
2403 if (!hitView && [[self superview] mouse:*aPoint inRect:[self frame]]) { |
|
2404 return self; |
|
2405 } else { |
|
2406 return hitView; |
|
2407 } |
|
2408 } |
|
2409 |
|
2410 - (BOOL)acceptsFirstResponder |
|
2411 { |
|
2412 return [[[self mainFrame] frameView] acceptsFirstResponder]; |
|
2413 } |
|
2414 |
|
2415 - (BOOL)becomeFirstResponder |
|
2416 { |
|
2417 if (_private->becomingFirstResponder) { |
|
2418 // Fix for unrepro infinite recursion reported in radar 4448181. If we hit this assert on |
|
2419 // a debug build, we should figure out what causes the problem and do a better fix. |
|
2420 ASSERT_NOT_REACHED(); |
|
2421 return NO; |
|
2422 } |
|
2423 |
|
2424 // This works together with setNextKeyView to splice the WebView into |
|
2425 // the key loop similar to the way NSScrollView does this. Note that |
|
2426 // WebFrameView has very similar code. |
|
2427 NSWindow *window = [self window]; |
|
2428 WebFrameView *mainFrameView = [[self mainFrame] frameView]; |
|
2429 |
|
2430 NSResponder *previousFirstResponder = [[self window] _oldFirstResponderBeforeBecoming]; |
|
2431 BOOL fromOutside = ![previousFirstResponder isKindOfClass:[NSView class]] || (![(NSView *)previousFirstResponder isDescendantOf:self] && previousFirstResponder != self); |
|
2432 |
|
2433 if ([window keyViewSelectionDirection] == NSSelectingPrevious) { |
|
2434 NSView *previousValidKeyView = [self previousValidKeyView]; |
|
2435 if ((previousValidKeyView != self) && (previousValidKeyView != mainFrameView)) { |
|
2436 _private->becomingFirstResponder = YES; |
|
2437 _private->becomingFirstResponderFromOutside = fromOutside; |
|
2438 [window makeFirstResponder:previousValidKeyView]; |
|
2439 _private->becomingFirstResponderFromOutside = NO; |
|
2440 _private->becomingFirstResponder = NO; |
|
2441 return YES; |
|
2442 } else { |
|
2443 return NO; |
|
2444 } |
|
2445 } |
|
2446 |
|
2447 if ([mainFrameView acceptsFirstResponder]) { |
|
2448 _private->becomingFirstResponder = YES; |
|
2449 _private->becomingFirstResponderFromOutside = fromOutside; |
|
2450 [window makeFirstResponder:mainFrameView]; |
|
2451 _private->becomingFirstResponderFromOutside = NO; |
|
2452 _private->becomingFirstResponder = NO; |
|
2453 return YES; |
|
2454 } |
|
2455 |
|
2456 return NO; |
|
2457 } |
|
2458 |
|
2459 - (NSView *)_webcore_effectiveFirstResponder |
|
2460 { |
|
2461 WebFrameView *frameView = [[self mainFrame] frameView]; |
|
2462 return frameView ? [frameView _webcore_effectiveFirstResponder] : [super _webcore_effectiveFirstResponder]; |
|
2463 } |
|
2464 |
|
2465 - (void)setNextKeyView:(NSView *)aView |
|
2466 { |
|
2467 // This works together with becomeFirstResponder to splice the WebView into |
|
2468 // the key loop similar to the way NSScrollView does this. Note that |
|
2469 // WebFrameView has very similar code. |
|
2470 WebFrameView *mainFrameView = [[self mainFrame] frameView]; |
|
2471 if (mainFrameView != nil) { |
|
2472 [mainFrameView setNextKeyView:aView]; |
|
2473 } else { |
|
2474 [super setNextKeyView:aView]; |
|
2475 } |
|
2476 } |
|
2477 |
|
2478 static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag) |
|
2479 { |
|
2480 Frame* coreFrame = core(curr); |
|
2481 return kit(forward |
|
2482 ? coreFrame->tree()->traverseNextWithWrap(wrapFlag) |
|
2483 : coreFrame->tree()->traversePreviousWithWrap(wrapFlag)); |
|
2484 } |
|
2485 |
|
2486 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag |
|
2487 { |
|
2488 return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO]; |
|
2489 } |
|
2490 |
|
2491 + (void)registerViewClass:(Class)viewClass representationClass:(Class)representationClass forMIMEType:(NSString *)MIMEType |
|
2492 { |
|
2493 [[WebFrameView _viewTypesAllowImageTypeOmission:YES] setObject:viewClass forKey:MIMEType]; |
|
2494 [[WebDataSource _repTypesAllowImageTypeOmission:YES] setObject:representationClass forKey:MIMEType]; |
|
2495 |
|
2496 // FIXME: We also need to maintain MIMEType registrations (which can be dynamically changed) |
|
2497 // in the WebCore MIMEType registry. For now we're doing this in a safe, limited manner |
|
2498 // to fix <rdar://problem/5372989> - a future revamping of the entire system is neccesary for future robustness |
|
2499 if ([viewClass class] == [WebHTMLView class]) |
|
2500 MIMETypeRegistry::getSupportedNonImageMIMETypes().add(MIMEType); |
|
2501 } |
|
2502 |
|
2503 - (void)setGroupName:(NSString *)groupName |
|
2504 { |
|
2505 if (!_private->page) |
|
2506 return; |
|
2507 _private->page->setGroupName(groupName); |
|
2508 } |
|
2509 |
|
2510 - (NSString *)groupName |
|
2511 { |
|
2512 if (!_private->page) |
|
2513 return nil; |
|
2514 return _private->page->groupName(); |
|
2515 } |
|
2516 |
|
2517 - (double)estimatedProgress |
|
2518 { |
|
2519 if (!_private->page) |
|
2520 return 0.0; |
|
2521 |
|
2522 return _private->page->progress()->estimatedProgress(); |
|
2523 } |
|
2524 |
|
2525 - (NSArray *)pasteboardTypesForSelection |
|
2526 { |
|
2527 NSView <WebDocumentView> *documentView = [[[self _selectedOrMainFrame] frameView] documentView]; |
|
2528 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) { |
|
2529 return [(NSView <WebDocumentSelection> *)documentView pasteboardTypesForSelection]; |
|
2530 } |
|
2531 return [NSArray array]; |
|
2532 } |
|
2533 |
|
2534 - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard |
|
2535 { |
|
2536 WebFrame *frame = [self _selectedOrMainFrame]; |
|
2537 if (frame && [frame _hasSelection]) { |
|
2538 NSView <WebDocumentView> *documentView = [[frame frameView] documentView]; |
|
2539 if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) |
|
2540 [(NSView <WebDocumentSelection> *)documentView writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard]; |
|
2541 } |
|
2542 } |
|
2543 |
|
2544 - (NSArray *)pasteboardTypesForElement:(NSDictionary *)element |
|
2545 { |
|
2546 if ([element objectForKey:WebElementImageURLKey] != nil) { |
|
2547 return [NSPasteboard _web_writableTypesForImageIncludingArchive:([element objectForKey:WebElementDOMNodeKey] != nil)]; |
|
2548 } else if ([element objectForKey:WebElementLinkURLKey] != nil) { |
|
2549 return [NSPasteboard _web_writableTypesForURL]; |
|
2550 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) { |
|
2551 return [self pasteboardTypesForSelection]; |
|
2552 } |
|
2553 return [NSArray array]; |
|
2554 } |
|
2555 |
|
2556 - (void)writeElement:(NSDictionary *)element withPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard |
|
2557 { |
|
2558 if ([element objectForKey:WebElementImageURLKey] != nil) { |
|
2559 [self _writeImageForElement:element withPasteboardTypes:types toPasteboard:pasteboard]; |
|
2560 } else if ([element objectForKey:WebElementLinkURLKey] != nil) { |
|
2561 [self _writeLinkElement:element withPasteboardTypes:types toPasteboard:pasteboard]; |
|
2562 } else if ([[element objectForKey:WebElementIsSelectedKey] boolValue]) { |
|
2563 [self writeSelectionWithPasteboardTypes:types toPasteboard:pasteboard]; |
|
2564 } |
|
2565 } |
|
2566 |
|
2567 - (void)moveDragCaretToPoint:(NSPoint)point |
|
2568 { |
|
2569 if (Page* page = core(self)) |
|
2570 page->dragController()->placeDragCaret(IntPoint([self convertPoint:point toView:nil])); |
|
2571 } |
|
2572 |
|
2573 - (void)removeDragCaret |
|
2574 { |
|
2575 if (Page* page = core(self)) |
|
2576 page->dragController()->dragEnded(); |
|
2577 } |
|
2578 |
|
2579 - (void)setMainFrameURL:(NSString *)URLString |
|
2580 { |
|
2581 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]]; |
|
2582 } |
|
2583 |
|
2584 - (NSString *)mainFrameURL |
|
2585 { |
|
2586 WebDataSource *ds; |
|
2587 ds = [[self mainFrame] provisionalDataSource]; |
|
2588 if (!ds) |
|
2589 ds = [[self mainFrame] _dataSource]; |
|
2590 return [[[ds request] URL] _web_originalDataAsString]; |
|
2591 } |
|
2592 |
|
2593 - (BOOL)isLoading |
|
2594 { |
|
2595 LOG (Bindings, "isLoading = %d", (int)[self _isLoading]); |
|
2596 return [self _isLoading]; |
|
2597 } |
|
2598 |
|
2599 - (NSString *)mainFrameTitle |
|
2600 { |
|
2601 NSString *mainFrameTitle = [[[self mainFrame] _dataSource] pageTitle]; |
|
2602 return (mainFrameTitle != nil) ? mainFrameTitle : (NSString *)@""; |
|
2603 } |
|
2604 |
|
2605 - (NSImage *)mainFrameIcon |
|
2606 { |
|
2607 return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] _dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize]; |
|
2608 } |
|
2609 |
|
2610 - (DOMDocument *)mainFrameDocument |
|
2611 { |
|
2612 // only return the actual value if the state we're in gives NSTreeController |
|
2613 // enough time to release its observers on the old model |
|
2614 if (_private->mainFrameDocumentReady) |
|
2615 return [[self mainFrame] DOMDocument]; |
|
2616 return nil; |
|
2617 } |
|
2618 |
|
2619 - (void)setDrawsBackground:(BOOL)drawsBackground |
|
2620 { |
|
2621 if (_private->drawsBackground == drawsBackground) |
|
2622 return; |
|
2623 _private->drawsBackground = drawsBackground; |
|
2624 [[self mainFrame] _updateBackground]; |
|
2625 } |
|
2626 |
|
2627 - (BOOL)drawsBackground |
|
2628 { |
|
2629 return _private->drawsBackground; |
|
2630 } |
|
2631 |
|
2632 @end |
|
2633 |
|
2634 @implementation WebView (WebIBActions) |
|
2635 |
|
2636 - (IBAction)takeStringURLFrom: sender |
|
2637 { |
|
2638 NSString *URLString = [sender stringValue]; |
|
2639 |
|
2640 [[self mainFrame] loadRequest: [NSURLRequest requestWithURL: [NSURL _web_URLWithDataAsString: URLString]]]; |
|
2641 } |
|
2642 |
|
2643 - (BOOL)canGoBack |
|
2644 { |
|
2645 if (!_private->page) |
|
2646 return NO; |
|
2647 |
|
2648 return !!_private->page->backForwardList()->backItem(); |
|
2649 } |
|
2650 |
|
2651 - (BOOL)canGoForward |
|
2652 { |
|
2653 if (!_private->page) |
|
2654 return NO; |
|
2655 |
|
2656 return !!_private->page->backForwardList()->forwardItem(); |
|
2657 } |
|
2658 |
|
2659 - (IBAction)goBack:(id)sender |
|
2660 { |
|
2661 [self goBack]; |
|
2662 } |
|
2663 |
|
2664 - (IBAction)goForward:(id)sender |
|
2665 { |
|
2666 [self goForward]; |
|
2667 } |
|
2668 |
|
2669 - (IBAction)stopLoading:(id)sender |
|
2670 { |
|
2671 [[self mainFrame] stopLoading]; |
|
2672 } |
|
2673 |
|
2674 - (IBAction)reload:(id)sender |
|
2675 { |
|
2676 [[self mainFrame] reload]; |
|
2677 } |
|
2678 |
|
2679 #define MinimumTextSizeMultiplier 0.5f |
|
2680 #define MaximumTextSizeMultiplier 3.0f |
|
2681 #define TextSizeMultiplierRatio 1.2f |
|
2682 |
|
2683 - (BOOL)canMakeTextSmaller |
|
2684 { |
|
2685 BOOL canShrinkMore = _private->textSizeMultiplier/TextSizeMultiplierRatio > MinimumTextSizeMultiplier; |
|
2686 return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:0]; |
|
2687 } |
|
2688 |
|
2689 - (BOOL)canMakeTextLarger |
|
2690 { |
|
2691 BOOL canGrowMore = _private->textSizeMultiplier*TextSizeMultiplierRatio < MaximumTextSizeMultiplier; |
|
2692 return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:0]; |
|
2693 } |
|
2694 |
|
2695 - (IBAction)makeTextSmaller:(id)sender |
|
2696 { |
|
2697 float newScale = _private->textSizeMultiplier / TextSizeMultiplierRatio; |
|
2698 BOOL canShrinkMore = newScale > MinimumTextSizeMultiplier; |
|
2699 [self _performTextSizingSelector:@selector(_makeTextSmaller:) withObject:sender onTrackingDocs:canShrinkMore selForNonTrackingDocs:@selector(_canMakeTextSmaller) newScaleFactor:newScale]; |
|
2700 } |
|
2701 |
|
2702 - (IBAction)makeTextLarger:(id)sender |
|
2703 { |
|
2704 float newScale = _private->textSizeMultiplier*TextSizeMultiplierRatio; |
|
2705 BOOL canGrowMore = newScale < MaximumTextSizeMultiplier; |
|
2706 [self _performTextSizingSelector:@selector(_makeTextLarger:) withObject:sender onTrackingDocs:canGrowMore selForNonTrackingDocs:@selector(_canMakeTextLarger) newScaleFactor:newScale]; |
|
2707 } |
|
2708 |
|
2709 - (IBAction)toggleSmartInsertDelete:(id)sender |
|
2710 { |
|
2711 [self setSmartInsertDeleteEnabled:![self smartInsertDeleteEnabled]]; |
|
2712 } |
|
2713 |
|
2714 - (IBAction)toggleContinuousSpellChecking:(id)sender |
|
2715 { |
|
2716 [self setContinuousSpellCheckingEnabled:![self isContinuousSpellCheckingEnabled]]; |
|
2717 } |
|
2718 |
|
2719 - (BOOL)_responderValidateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item |
|
2720 { |
|
2721 id responder = [self _responderForResponderOperations]; |
|
2722 if (responder != self && [responder respondsToSelector:[item action]]) { |
|
2723 if ([responder respondsToSelector:@selector(validateUserInterfaceItemWithoutDelegate:)]) |
|
2724 return [responder validateUserInterfaceItemWithoutDelegate:item]; |
|
2725 if ([responder respondsToSelector:@selector(validateUserInterfaceItem:)]) |
|
2726 return [responder validateUserInterfaceItem:item]; |
|
2727 return YES; |
|
2728 } |
|
2729 return NO; |
|
2730 } |
|
2731 |
|
2732 - (BOOL)canMakeTextStandardSize |
|
2733 { |
|
2734 BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f; |
|
2735 return [self _performTextSizingSelector:(SEL)0 withObject:nil onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:0.0f]; |
|
2736 } |
|
2737 |
|
2738 - (IBAction)makeTextStandardSize:(id)sender |
|
2739 { |
|
2740 BOOL notAlreadyStandard = _private->textSizeMultiplier != 1.0f; |
|
2741 [self _performTextSizingSelector:@selector(_makeTextStandardSize:) withObject:sender onTrackingDocs:notAlreadyStandard selForNonTrackingDocs:@selector(_canMakeTextStandardSize) newScaleFactor:1.0f]; |
|
2742 } |
|
2743 |
|
2744 #define VALIDATE(name) \ |
|
2745 else if (action == @selector(name:)) { return [self _responderValidateUserInterfaceItem:item]; } |
|
2746 |
|
2747 - (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item |
|
2748 { |
|
2749 SEL action = [item action]; |
|
2750 |
|
2751 if (action == @selector(goBack:)) { |
|
2752 return [self canGoBack]; |
|
2753 } else if (action == @selector(goForward:)) { |
|
2754 return [self canGoForward]; |
|
2755 } else if (action == @selector(makeTextLarger:)) { |
|
2756 return [self canMakeTextLarger]; |
|
2757 } else if (action == @selector(makeTextSmaller:)) { |
|
2758 return [self canMakeTextSmaller]; |
|
2759 } else if (action == @selector(makeTextStandardSize:)) { |
|
2760 return [self canMakeTextStandardSize]; |
|
2761 } else if (action == @selector(reload:)) { |
|
2762 return [[self mainFrame] _dataSource] != nil; |
|
2763 } else if (action == @selector(stopLoading:)) { |
|
2764 return [self _isLoading]; |
|
2765 } else if (action == @selector(toggleContinuousSpellChecking:)) { |
|
2766 BOOL checkMark = NO; |
|
2767 BOOL retVal = NO; |
|
2768 if ([self _continuousCheckingAllowed]) { |
|
2769 checkMark = [self isContinuousSpellCheckingEnabled]; |
|
2770 retVal = YES; |
|
2771 } |
|
2772 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { |
|
2773 NSMenuItem *menuItem = (NSMenuItem *)item; |
|
2774 [menuItem setState:checkMark ? NSOnState : NSOffState]; |
|
2775 } |
|
2776 return retVal; |
|
2777 #ifndef BUILDING_ON_TIGER |
|
2778 } else if (action == @selector(toggleGrammarChecking:)) { |
|
2779 BOOL checkMark = [self isGrammarCheckingEnabled]; |
|
2780 if ([(NSObject *)item isKindOfClass:[NSMenuItem class]]) { |
|
2781 NSMenuItem *menuItem = (NSMenuItem *)item; |
|
2782 [menuItem setState:checkMark ? NSOnState : NSOffState]; |
|
2783 } |
|
2784 return YES; |
|
2785 #endif |
|
2786 } |
|
2787 FOR_EACH_RESPONDER_SELECTOR(VALIDATE) |
|
2788 |
|
2789 return YES; |
|
2790 } |
|
2791 |
|
2792 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item |
|
2793 { |
|
2794 BOOL result = [self validateUserInterfaceItemWithoutDelegate:item]; |
|
2795 return CallUIDelegateReturningBoolean(result, self, @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result); |
|
2796 } |
|
2797 |
|
2798 @end |
|
2799 |
|
2800 @implementation WebView (WebPendingPublic) |
|
2801 |
|
2802 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection |
|
2803 { |
|
2804 if (_private->closed) |
|
2805 return NO; |
|
2806 |
|
2807 // Get the frame holding the selection, or start with the main frame |
|
2808 WebFrame *startFrame = [self _selectedOrMainFrame]; |
|
2809 |
|
2810 // Search the first frame, then all the other frames, in order |
|
2811 NSView <WebDocumentSearching> *startSearchView = nil; |
|
2812 WebFrame *frame = startFrame; |
|
2813 do { |
|
2814 WebFrame *nextFrame = incrementFrame(frame, forward, wrapFlag); |
|
2815 |
|
2816 BOOL onlyOneFrame = (frame == nextFrame); |
|
2817 ASSERT(!onlyOneFrame || frame == startFrame); |
|
2818 |
|
2819 id <WebDocumentView> view = [[frame frameView] documentView]; |
|
2820 if ([view conformsToProtocol:@protocol(WebDocumentSearching)]) { |
|
2821 NSView <WebDocumentSearching> *searchView = (NSView <WebDocumentSearching> *)view; |
|
2822 |
|
2823 if (frame == startFrame) |
|
2824 startSearchView = searchView; |
|
2825 |
|
2826 BOOL foundString; |
|
2827 // In some cases we have to search some content twice; see comment later in this method. |
|
2828 // We can avoid ever doing this in the common one-frame case by passing YES for wrapFlag |
|
2829 // here, and then bailing out before we get to the code that would search again in the |
|
2830 // same content. |
|
2831 BOOL wrapOnThisPass = wrapFlag && onlyOneFrame; |
|
2832 if ([searchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)]) |
|
2833 foundString = [(NSView <WebDocumentIncrementalSearching> *)searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass startInSelection:startInSelection]; |
|
2834 else |
|
2835 foundString = [searchView searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapOnThisPass]; |
|
2836 |
|
2837 if (foundString) { |
|
2838 if (frame != startFrame) |
|
2839 [startFrame _clearSelection]; |
|
2840 [[self window] makeFirstResponder:searchView]; |
|
2841 return YES; |
|
2842 } |
|
2843 |
|
2844 if (onlyOneFrame) |
|
2845 return NO; |
|
2846 } |
|
2847 frame = nextFrame; |
|
2848 } while (frame && frame != startFrame); |
|
2849 |
|
2850 // If there are multiple frames and wrapFlag is true and we've visited each one without finding a result, we still need to search in the |
|
2851 // first-searched frame up to the selection. However, the API doesn't provide a way to search only up to a particular point. The only |
|
2852 // way to make sure the entire frame is searched is to pass YES for the wrapFlag. When there are no matches, this will search again |
|
2853 // some content that we already searched on the first pass. In the worst case, we could search the entire contents of this frame twice. |
|
2854 // To fix this, we'd need to add a mechanism to specify a range in which to search. |
|
2855 if (wrapFlag && startSearchView) { |
|
2856 BOOL foundString; |
|
2857 if ([startSearchView conformsToProtocol:@protocol(WebDocumentIncrementalSearching)]) |
|
2858 foundString = [(NSView <WebDocumentIncrementalSearching> *)startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES startInSelection:startInSelection]; |
|
2859 else |
|
2860 foundString = [startSearchView searchFor:string direction:forward caseSensitive:caseFlag wrap:YES]; |
|
2861 if (foundString) { |
|
2862 [[self window] makeFirstResponder:startSearchView]; |
|
2863 return YES; |
|
2864 } |
|
2865 } |
|
2866 return NO; |
|
2867 } |
|
2868 |
|
2869 - (void)setHoverFeedbackSuspended:(BOOL)newValue |
|
2870 { |
|
2871 if (_private->hoverFeedbackSuspended == newValue) |
|
2872 return; |
|
2873 |
|
2874 _private->hoverFeedbackSuspended = newValue; |
|
2875 id <WebDocumentView> documentView = [[[self mainFrame] frameView] documentView]; |
|
2876 // FIXME: in a perfect world we'd do this in a general way that worked with any document view, |
|
2877 // such as by calling a protocol method or using respondsToSelector or sending a notification. |
|
2878 // But until there is any need for these more general solutions, we'll just hardwire it to work |
|
2879 // with WebHTMLView. |
|
2880 // Note that _hoverFeedbackSuspendedChanged needs to be called only on the main WebHTMLView, not |
|
2881 // on each subframe separately. |
|
2882 if ([documentView isKindOfClass:[WebHTMLView class]]) |
|
2883 [(WebHTMLView *)documentView _hoverFeedbackSuspendedChanged]; |
|
2884 } |
|
2885 |
|
2886 - (BOOL)isHoverFeedbackSuspended |
|
2887 { |
|
2888 return _private->hoverFeedbackSuspended; |
|
2889 } |
|
2890 |
|
2891 - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady |
|
2892 { |
|
2893 // by setting this to NO, calls to mainFrameDocument are forced to return nil |
|
2894 // setting this to YES lets it return the actual DOMDocument value |
|
2895 // we use this to tell NSTreeController to reset its observers and clear its state |
|
2896 if (_private->mainFrameDocumentReady == mainFrameDocumentReady) |
|
2897 return; |
|
2898 [self _willChangeValueForKey:_WebMainFrameDocumentKey]; |
|
2899 _private->mainFrameDocumentReady = mainFrameDocumentReady; |
|
2900 [self _didChangeValueForKey:_WebMainFrameDocumentKey]; |
|
2901 // this will cause observers to call mainFrameDocument where this flag will be checked |
|
2902 } |
|
2903 |
|
2904 // This method name is used by Mail on Tiger (but not post-Tiger), so we shouldn't delete it |
|
2905 // until the day comes when we're no longer supporting Mail on Tiger. |
|
2906 - (WebFrame *)_frameForCurrentSelection |
|
2907 { |
|
2908 return [self _selectedOrMainFrame]; |
|
2909 } |
|
2910 |
|
2911 - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements |
|
2912 { |
|
2913 _private->tabKeyCyclesThroughElementsChanged = YES; |
|
2914 if (_private->page) |
|
2915 _private->page->setTabKeyCyclesThroughElements(cyclesElements); |
|
2916 } |
|
2917 |
|
2918 - (BOOL)tabKeyCyclesThroughElements |
|
2919 { |
|
2920 return _private->page && _private->page->tabKeyCyclesThroughElements(); |
|
2921 } |
|
2922 |
|
2923 - (void)setScriptDebugDelegate:(id)delegate |
|
2924 { |
|
2925 _private->scriptDebugDelegate = delegate; |
|
2926 [_private->scriptDebugDelegateForwarder release]; |
|
2927 _private->scriptDebugDelegateForwarder = nil; |
|
2928 if (delegate) |
|
2929 [self _attachScriptDebuggerToAllFrames]; |
|
2930 else |
|
2931 [self _detachScriptDebuggerFromAllFrames]; |
|
2932 } |
|
2933 |
|
2934 - (id)scriptDebugDelegate |
|
2935 { |
|
2936 return _private->scriptDebugDelegate; |
|
2937 } |
|
2938 |
|
2939 - (BOOL)shouldClose |
|
2940 { |
|
2941 Frame* coreFrame = core([self mainFrame]); |
|
2942 if (!coreFrame) |
|
2943 return YES; |
|
2944 return coreFrame->shouldClose(); |
|
2945 } |
|
2946 |
|
2947 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)script |
|
2948 { |
|
2949 return [[[self mainFrame] _bridge] aeDescByEvaluatingJavaScriptFromString:script]; |
|
2950 } |
|
2951 |
|
2952 - (BOOL)canMarkAllTextMatches |
|
2953 { |
|
2954 WebFrame *frame = [self mainFrame]; |
|
2955 do { |
|
2956 id <WebDocumentView> view = [[frame frameView] documentView]; |
|
2957 if (view && ![view conformsToProtocol:@protocol(WebMultipleTextMatches)]) |
|
2958 return NO; |
|
2959 |
|
2960 frame = incrementFrame(frame, YES, NO); |
|
2961 } while (frame); |
|
2962 |
|
2963 return YES; |
|
2964 } |
|
2965 |
|
2966 - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit |
|
2967 { |
|
2968 WebFrame *frame = [self mainFrame]; |
|
2969 unsigned matchCount = 0; |
|
2970 do { |
|
2971 id <WebDocumentView> view = [[frame frameView] documentView]; |
|
2972 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { |
|
2973 [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight]; |
|
2974 |
|
2975 ASSERT(limit == 0 || matchCount < limit); |
|
2976 matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount]; |
|
2977 |
|
2978 // Stop looking if we've reached the limit. A limit of 0 means no limit. |
|
2979 if (limit > 0 && matchCount >= limit) |
|
2980 break; |
|
2981 } |
|
2982 |
|
2983 frame = incrementFrame(frame, YES, NO); |
|
2984 } while (frame); |
|
2985 |
|
2986 return matchCount; |
|
2987 } |
|
2988 |
|
2989 - (void)unmarkAllTextMatches |
|
2990 { |
|
2991 WebFrame *frame = [self mainFrame]; |
|
2992 do { |
|
2993 id <WebDocumentView> view = [[frame frameView] documentView]; |
|
2994 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) |
|
2995 [(NSView <WebMultipleTextMatches>*)view unmarkAllTextMatches]; |
|
2996 |
|
2997 frame = incrementFrame(frame, YES, NO); |
|
2998 } while (frame); |
|
2999 } |
|
3000 |
|
3001 - (NSArray *)rectsForTextMatches |
|
3002 { |
|
3003 NSMutableArray *result = [NSMutableArray array]; |
|
3004 WebFrame *frame = [self mainFrame]; |
|
3005 do { |
|
3006 id <WebDocumentView> view = [[frame frameView] documentView]; |
|
3007 if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { |
|
3008 NSView <WebMultipleTextMatches> *documentView = (NSView <WebMultipleTextMatches> *)view; |
|
3009 NSRect documentViewVisibleRect = [documentView visibleRect]; |
|
3010 NSArray *originalRects = [documentView rectsForTextMatches]; |
|
3011 unsigned rectCount = [originalRects count]; |
|
3012 unsigned rectIndex; |
|
3013 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
|
3014 for (rectIndex = 0; rectIndex < rectCount; ++rectIndex) { |
|
3015 NSRect r = [[originalRects objectAtIndex:rectIndex] rectValue]; |
|
3016 // Clip rect to document view's visible rect so rect is confined to subframe |
|
3017 r = NSIntersectionRect(r, documentViewVisibleRect); |
|
3018 if (NSIsEmptyRect(r)) |
|
3019 continue; |
|
3020 |
|
3021 // Convert rect to our coordinate system |
|
3022 r = [documentView convertRect:r toView:self]; |
|
3023 [result addObject:[NSValue valueWithRect:r]]; |
|
3024 if (rectIndex % 10 == 0) { |
|
3025 [pool drain]; |
|
3026 pool = [[NSAutoreleasePool alloc] init]; |
|
3027 } |
|
3028 } |
|
3029 [pool drain]; |
|
3030 } |
|
3031 |
|
3032 frame = incrementFrame(frame, YES, NO); |
|
3033 } while (frame); |
|
3034 |
|
3035 return result; |
|
3036 } |
|
3037 |
|
3038 - (void)scrollDOMRangeToVisible:(DOMRange *)range |
|
3039 { |
|
3040 [[[range startContainer] _bridge] scrollDOMRangeToVisible:range]; |
|
3041 } |
|
3042 |
|
3043 - (BOOL)allowsUndo |
|
3044 { |
|
3045 return _private->allowsUndo; |
|
3046 } |
|
3047 |
|
3048 - (void)setAllowsUndo:(BOOL)flag |
|
3049 { |
|
3050 _private->allowsUndo = flag; |
|
3051 } |
|
3052 |
|
3053 @end |
|
3054 |
|
3055 @implementation WebView (WebViewPrintingPrivate) |
|
3056 |
|
3057 - (float)_headerHeight |
|
3058 { |
|
3059 return CallUIDelegateReturningFloat(self, @selector(webViewHeaderHeight:)); |
|
3060 } |
|
3061 |
|
3062 - (float)_footerHeight |
|
3063 { |
|
3064 return CallUIDelegateReturningFloat(self, @selector(webViewFooterHeight:)); |
|
3065 } |
|
3066 |
|
3067 - (void)_drawHeaderInRect:(NSRect)rect |
|
3068 { |
|
3069 #ifdef DEBUG_HEADER_AND_FOOTER |
|
3070 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; |
|
3071 [currentContext saveGraphicsState]; |
|
3072 [[NSColor yellowColor] set]; |
|
3073 NSRectFill(rect); |
|
3074 [currentContext restoreGraphicsState]; |
|
3075 #endif |
|
3076 |
|
3077 SEL selector = @selector(webView:drawHeaderInRect:); |
|
3078 if (![_private->UIDelegate respondsToSelector:selector]) |
|
3079 return; |
|
3080 |
|
3081 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; |
|
3082 [currentContext saveGraphicsState]; |
|
3083 |
|
3084 NSRectClip(rect); |
|
3085 CallUIDelegate(self, selector, rect); |
|
3086 |
|
3087 [currentContext restoreGraphicsState]; |
|
3088 } |
|
3089 |
|
3090 - (void)_drawFooterInRect:(NSRect)rect |
|
3091 { |
|
3092 #ifdef DEBUG_HEADER_AND_FOOTER |
|
3093 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; |
|
3094 [currentContext saveGraphicsState]; |
|
3095 [[NSColor cyanColor] set]; |
|
3096 NSRectFill(rect); |
|
3097 [currentContext restoreGraphicsState]; |
|
3098 #endif |
|
3099 |
|
3100 SEL selector = @selector(webView:drawFooterInRect:); |
|
3101 if (![_private->UIDelegate respondsToSelector:selector]) |
|
3102 return; |
|
3103 |
|
3104 NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; |
|
3105 [currentContext saveGraphicsState]; |
|
3106 |
|
3107 NSRectClip(rect); |
|
3108 CallUIDelegate(self, selector, rect); |
|
3109 |
|
3110 [currentContext restoreGraphicsState]; |
|
3111 } |
|
3112 |
|
3113 - (void)_adjustPrintingMarginsForHeaderAndFooter |
|
3114 { |
|
3115 NSPrintOperation *op = [NSPrintOperation currentOperation]; |
|
3116 NSPrintInfo *info = [op printInfo]; |
|
3117 NSMutableDictionary *infoDictionary = [info dictionary]; |
|
3118 |
|
3119 // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the |
|
3120 // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087), |
|
3121 // we stash away the unmodified top and bottom margins the first time this method is called, and we read from |
|
3122 // those stashed-away values on subsequent calls. |
|
3123 float originalTopMargin; |
|
3124 float originalBottomMargin; |
|
3125 NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey]; |
|
3126 if (!originalTopMarginNumber) { |
|
3127 ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]); |
|
3128 originalTopMargin = [info topMargin]; |
|
3129 originalBottomMargin = [info bottomMargin]; |
|
3130 [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey]; |
|
3131 [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey]; |
|
3132 } else { |
|
3133 ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]); |
|
3134 ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]); |
|
3135 originalTopMargin = [originalTopMarginNumber floatValue]; |
|
3136 originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue]; |
|
3137 } |
|
3138 |
|
3139 float scale = [op _web_pageSetupScaleFactor]; |
|
3140 [info setTopMargin:originalTopMargin + [self _headerHeight] * scale]; |
|
3141 [info setBottomMargin:originalBottomMargin + [self _footerHeight] * scale]; |
|
3142 } |
|
3143 |
|
3144 - (void)_drawHeaderAndFooter |
|
3145 { |
|
3146 // The header and footer rect height scales with the page, but the width is always |
|
3147 // all the way across the printed page (inset by printing margins). |
|
3148 NSPrintOperation *op = [NSPrintOperation currentOperation]; |
|
3149 float scale = [op _web_pageSetupScaleFactor]; |
|
3150 NSPrintInfo *printInfo = [op printInfo]; |
|
3151 NSSize paperSize = [printInfo paperSize]; |
|
3152 float headerFooterLeft = [printInfo leftMargin]/scale; |
|
3153 float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin]))/scale; |
|
3154 NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin]/scale - [self _footerHeight] , |
|
3155 headerFooterWidth, [self _footerHeight]); |
|
3156 NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin])/scale, |
|
3157 headerFooterWidth, [self _headerHeight]); |
|
3158 |
|
3159 [self _drawHeaderInRect:headerRect]; |
|
3160 [self _drawFooterInRect:footerRect]; |
|
3161 } |
|
3162 @end |
|
3163 |
|
3164 @implementation WebView (WebDebugBinding) |
|
3165 |
|
3166 - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context |
|
3167 { |
|
3168 LOG (Bindings, "addObserver:%p forKeyPath:%@ options:%x context:%p", anObserver, keyPath, options, context); |
|
3169 [super addObserver:anObserver forKeyPath:keyPath options:options context:context]; |
|
3170 } |
|
3171 |
|
3172 - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath |
|
3173 { |
|
3174 LOG (Bindings, "removeObserver:%p forKeyPath:%@", anObserver, keyPath); |
|
3175 [super removeObserver:anObserver forKeyPath:keyPath]; |
|
3176 } |
|
3177 |
|
3178 @end |
|
3179 |
|
3180 //========================================================================================== |
|
3181 // Editing |
|
3182 |
|
3183 @implementation WebView (WebViewCSS) |
|
3184 |
|
3185 - (DOMCSSStyleDeclaration *)computedStyleForElement:(DOMElement *)element pseudoElement:(NSString *)pseudoElement |
|
3186 { |
|
3187 // FIXME: is this the best level for this conversion? |
|
3188 if (pseudoElement == nil) { |
|
3189 pseudoElement = @""; |
|
3190 } |
|
3191 return [[element ownerDocument] getComputedStyle:element pseudoElement:pseudoElement]; |
|
3192 } |
|
3193 |
|
3194 @end |
|
3195 |
|
3196 @implementation WebView (WebViewEditing) |
|
3197 |
|
3198 - (DOMRange *)editableDOMRangeForPoint:(NSPoint)point |
|
3199 { |
|
3200 Page* page = core(self); |
|
3201 if (!page) |
|
3202 return nil; |
|
3203 return kit(page->mainFrame()->editor()->rangeForPoint(IntPoint([self convertPoint:point toView:nil])).get()); |
|
3204 } |
|
3205 |
|
3206 - (BOOL)_shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange affinity:(NSSelectionAffinity)selectionAffinity stillSelecting:(BOOL)flag; |
|
3207 { |
|
3208 // FIXME: This quirk is needed due to <rdar://problem/4985321> - We can phase it out once Aperture can adopt the new behavior on their end |
|
3209 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_APERTURE_QUIRK) && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Aperture"]) |
|
3210 return YES; |
|
3211 return [[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange affinity:selectionAffinity stillSelecting:flag]; |
|
3212 } |
|
3213 |
|
3214 - (BOOL)maintainsInactiveSelection |
|
3215 { |
|
3216 return NO; |
|
3217 } |
|
3218 |
|
3219 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity |
|
3220 { |
|
3221 Frame* coreFrame = core([self _selectedOrMainFrame]); |
|
3222 if (!coreFrame) |
|
3223 return; |
|
3224 |
|
3225 if (range == nil) |
|
3226 coreFrame->selectionController()->clear(); |
|
3227 else { |
|
3228 // Derive the frame to use from the range passed in. |
|
3229 // Using _bridgeForSelectedOrMainFrame could give us a different document than |
|
3230 // the one the range uses. |
|
3231 coreFrame = core([range startContainer])->document()->frame(); |
|
3232 if (!coreFrame) |
|
3233 return; |
|
3234 |
|
3235 ExceptionCode ec = 0; |
|
3236 coreFrame->selectionController()->setSelectedRange([range _range], core(selectionAffinity), true, ec); |
|
3237 } |
|
3238 } |
|
3239 |
|
3240 - (DOMRange *)selectedDOMRange |
|
3241 { |
|
3242 Frame* coreFrame = core([self _selectedOrMainFrame]); |
|
3243 if (!coreFrame) |
|
3244 return nil; |
|
3245 return kit(coreFrame->selectionController()->toRange().get()); |
|
3246 } |
|
3247 |
|
3248 - (NSSelectionAffinity)selectionAffinity |
|
3249 { |
|
3250 Frame* coreFrame = core([self _selectedOrMainFrame]); |
|
3251 if (!coreFrame) |
|
3252 return NSSelectionAffinityDownstream; |
|
3253 return kit(coreFrame->selectionController()->affinity()); |
|
3254 } |
|
3255 |
|
3256 - (void)setEditable:(BOOL)flag |
|
3257 { |
|
3258 if (_private->editable != flag) { |
|
3259 _private->editable = flag; |
|
3260 if (!_private->tabKeyCyclesThroughElementsChanged && _private->page) |
|
3261 _private->page->setTabKeyCyclesThroughElements(!flag); |
|
3262 Frame* mainFrame = [[[self mainFrame] _bridge] _frame]; |
|
3263 if (mainFrame) { |
|
3264 if (flag) { |
|
3265 mainFrame->applyEditingStyleToBodyElement(); |
|
3266 // If the WebView is made editable and the selection is empty, set it to something. |
|
3267 if (![self selectedDOMRange]) |
|
3268 mainFrame->setSelectionFromNone(); |
|
3269 } else |
|
3270 mainFrame->removeEditingStyleFromBodyElement(); |
|
3271 } |
|
3272 } |
|
3273 } |
|
3274 |
|
3275 - (BOOL)isEditable |
|
3276 { |
|
3277 return _private->editable; |
|
3278 } |
|
3279 |
|
3280 - (void)setTypingStyle:(DOMCSSStyleDeclaration *)style |
|
3281 { |
|
3282 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to |
|
3283 // change the API to allow this. |
|
3284 [[self _bridgeForSelectedOrMainFrame] setTypingStyle:style withUndoAction:EditActionUnspecified]; |
|
3285 } |
|
3286 |
|
3287 - (DOMCSSStyleDeclaration *)typingStyle |
|
3288 { |
|
3289 return [[self _bridgeForSelectedOrMainFrame] typingStyle]; |
|
3290 } |
|
3291 |
|
3292 - (void)setSmartInsertDeleteEnabled:(BOOL)flag |
|
3293 { |
|
3294 _private->smartInsertDeleteEnabled = flag; |
|
3295 } |
|
3296 |
|
3297 - (BOOL)smartInsertDeleteEnabled |
|
3298 { |
|
3299 return _private->smartInsertDeleteEnabled; |
|
3300 } |
|
3301 |
|
3302 - (void)setContinuousSpellCheckingEnabled:(BOOL)flag |
|
3303 { |
|
3304 if (continuousSpellCheckingEnabled != flag) { |
|
3305 continuousSpellCheckingEnabled = flag; |
|
3306 [[NSUserDefaults standardUserDefaults] setBool:continuousSpellCheckingEnabled forKey:WebContinuousSpellCheckingEnabled]; |
|
3307 } |
|
3308 |
|
3309 if ([self isContinuousSpellCheckingEnabled]) { |
|
3310 [[self class] _preflightSpellChecker]; |
|
3311 } else { |
|
3312 [[self mainFrame] _unmarkAllMisspellings]; |
|
3313 } |
|
3314 } |
|
3315 |
|
3316 - (BOOL)isContinuousSpellCheckingEnabled |
|
3317 { |
|
3318 return (continuousSpellCheckingEnabled && [self _continuousCheckingAllowed]); |
|
3319 } |
|
3320 |
|
3321 - (NSInteger)spellCheckerDocumentTag |
|
3322 { |
|
3323 if (!_private->hasSpellCheckerDocumentTag) { |
|
3324 _private->spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag]; |
|
3325 _private->hasSpellCheckerDocumentTag = YES; |
|
3326 } |
|
3327 return _private->spellCheckerDocumentTag; |
|
3328 } |
|
3329 |
|
3330 - (NSUndoManager *)undoManager |
|
3331 { |
|
3332 if (!_private->allowsUndo) |
|
3333 return nil; |
|
3334 |
|
3335 NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self]; |
|
3336 if (undoManager) |
|
3337 return undoManager; |
|
3338 |
|
3339 return [super undoManager]; |
|
3340 } |
|
3341 |
|
3342 - (void)registerForEditingDelegateNotification:(NSString *)name selector:(SEL)selector |
|
3343 { |
|
3344 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; |
|
3345 if ([_private->editingDelegate respondsToSelector:selector]) |
|
3346 [defaultCenter addObserver:_private->editingDelegate selector:selector name:name object:self]; |
|
3347 } |
|
3348 |
|
3349 - (void)setEditingDelegate:(id)delegate |
|
3350 { |
|
3351 if (_private->editingDelegate == delegate) |
|
3352 return; |
|
3353 |
|
3354 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; |
|
3355 |
|
3356 // remove notifications from current delegate |
|
3357 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidBeginEditingNotification object:self]; |
|
3358 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeNotification object:self]; |
|
3359 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidEndEditingNotification object:self]; |
|
3360 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeTypingStyleNotification object:self]; |
|
3361 [defaultCenter removeObserver:_private->editingDelegate name:WebViewDidChangeSelectionNotification object:self]; |
|
3362 |
|
3363 _private->editingDelegate = delegate; |
|
3364 [_private->editingDelegateForwarder release]; |
|
3365 _private->editingDelegateForwarder = nil; |
|
3366 |
|
3367 // add notifications for new delegate |
|
3368 [self registerForEditingDelegateNotification:WebViewDidBeginEditingNotification selector:@selector(webViewDidBeginEditing:)]; |
|
3369 [self registerForEditingDelegateNotification:WebViewDidChangeNotification selector:@selector(webViewDidChange:)]; |
|
3370 [self registerForEditingDelegateNotification:WebViewDidEndEditingNotification selector:@selector(webViewDidEndEditing:)]; |
|
3371 [self registerForEditingDelegateNotification:WebViewDidChangeTypingStyleNotification selector:@selector(webViewDidChangeTypingStyle:)]; |
|
3372 [self registerForEditingDelegateNotification:WebViewDidChangeSelectionNotification selector:@selector(webViewDidChangeSelection:)]; |
|
3373 } |
|
3374 |
|
3375 - (id)editingDelegate |
|
3376 { |
|
3377 return _private->editingDelegate; |
|
3378 } |
|
3379 |
|
3380 - (DOMCSSStyleDeclaration *)styleDeclarationWithText:(NSString *)text |
|
3381 { |
|
3382 // FIXME: Should this really be attached to the document with the current selection? |
|
3383 DOMCSSStyleDeclaration *decl = [[[self _selectedOrMainFrame] DOMDocument] createCSSStyleDeclaration]; |
|
3384 [decl setCssText:text]; |
|
3385 return decl; |
|
3386 } |
|
3387 |
|
3388 @end |
|
3389 |
|
3390 @implementation WebView (WebViewGrammarChecking) |
|
3391 |
|
3392 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze |
|
3393 - (BOOL)isGrammarCheckingEnabled |
|
3394 { |
|
3395 #ifdef BUILDING_ON_TIGER |
|
3396 return NO; |
|
3397 #else |
|
3398 return grammarCheckingEnabled; |
|
3399 #endif |
|
3400 } |
|
3401 |
|
3402 #ifndef BUILDING_ON_TIGER |
|
3403 // FIXME: This method should be merged into WebViewEditing when we're not in API freeze |
|
3404 - (void)setGrammarCheckingEnabled:(BOOL)flag |
|
3405 { |
|
3406 if (grammarCheckingEnabled == flag) |
|
3407 return; |
|
3408 |
|
3409 grammarCheckingEnabled = flag; |
|
3410 [[NSUserDefaults standardUserDefaults] setBool:grammarCheckingEnabled forKey:WebGrammarCheckingEnabled]; |
|
3411 |
|
3412 // FIXME 4811447: workaround for lack of API |
|
3413 NSSpellChecker *spellChecker = [NSSpellChecker sharedSpellChecker]; |
|
3414 if ([spellChecker respondsToSelector:@selector(_updateGrammar)]) |
|
3415 [spellChecker performSelector:@selector(_updateGrammar)]; |
|
3416 |
|
3417 // We call _preflightSpellChecker when turning continuous spell checking on, but we don't need to do that here |
|
3418 // because grammar checking only occurs on code paths that already preflight spell checking appropriately. |
|
3419 |
|
3420 if (![self isGrammarCheckingEnabled]) |
|
3421 [[self mainFrame] _unmarkAllBadGrammar]; |
|
3422 } |
|
3423 |
|
3424 // FIXME: This method should be merged into WebIBActions when we're not in API freeze |
|
3425 - (void)toggleGrammarChecking:(id)sender |
|
3426 { |
|
3427 [self setGrammarCheckingEnabled:![self isGrammarCheckingEnabled]]; |
|
3428 } |
|
3429 #endif |
|
3430 |
|
3431 @end |
|
3432 |
|
3433 @implementation WebView (WebViewUndoableEditing) |
|
3434 |
|
3435 - (void)replaceSelectionWithNode:(DOMNode *)node |
|
3436 { |
|
3437 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:NO]; |
|
3438 } |
|
3439 |
|
3440 - (void)replaceSelectionWithText:(NSString *)text |
|
3441 { |
|
3442 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithText:text selectReplacement:YES smartReplace:NO]; |
|
3443 } |
|
3444 |
|
3445 - (void)replaceSelectionWithMarkupString:(NSString *)markupString |
|
3446 { |
|
3447 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithMarkupString:markupString baseURLString:nil selectReplacement:YES smartReplace:NO]; |
|
3448 } |
|
3449 |
|
3450 - (void)replaceSelectionWithArchive:(WebArchive *)archive |
|
3451 { |
|
3452 [[[[self _bridgeForSelectedOrMainFrame] webFrame] _dataSource] _replaceSelectionWithArchive:archive selectReplacement:YES]; |
|
3453 } |
|
3454 |
|
3455 - (void)deleteSelection |
|
3456 { |
|
3457 WebFrame *webFrame = [self _selectedOrMainFrame]; |
|
3458 Frame* coreFrame = core(webFrame); |
|
3459 if (coreFrame) |
|
3460 coreFrame->editor()->deleteSelectionWithSmartDelete([(WebHTMLView *)[[webFrame frameView] documentView] _canSmartCopyOrDelete]); |
|
3461 } |
|
3462 |
|
3463 - (void)applyStyle:(DOMCSSStyleDeclaration *)style |
|
3464 { |
|
3465 // We don't know enough at thls level to pass in a relevant WebUndoAction; we'd have to |
|
3466 // change the API to allow this. |
|
3467 WebFrame *webFrame = [self _selectedOrMainFrame]; |
|
3468 Frame* coreFrame = core(webFrame); |
|
3469 if (coreFrame) |
|
3470 coreFrame->editor()->applyStyle(core(style)); |
|
3471 } |
|
3472 |
|
3473 @end |
|
3474 |
|
3475 @implementation WebView (WebViewEditingActions) |
|
3476 |
|
3477 - (void)_performResponderOperation:(SEL)selector with:(id)parameter |
|
3478 { |
|
3479 static BOOL reentered = NO; |
|
3480 if (reentered) { |
|
3481 [[self nextResponder] tryToPerform:selector with:parameter]; |
|
3482 return; |
|
3483 } |
|
3484 |
|
3485 // There are two possibilities here. |
|
3486 // |
|
3487 // One is that WebView has been called in its role as part of the responder chain. |
|
3488 // In that case, it's fine to call the first responder and end up calling down the |
|
3489 // responder chain again. Later we will return here with reentered = YES and continue |
|
3490 // past the WebView. |
|
3491 // |
|
3492 // The other is that we are being called directly, in which case we want to pass the |
|
3493 // selector down to the view inside us that can handle it, and continue down the |
|
3494 // responder chain as usual. |
|
3495 |
|
3496 // Pass this selector down to the first responder. |
|
3497 NSResponder *responder = [self _responderForResponderOperations]; |
|
3498 reentered = YES; |
|
3499 [responder tryToPerform:selector with:parameter]; |
|
3500 reentered = NO; |
|
3501 } |
|
3502 |
|
3503 #define FORWARD(name) \ |
|
3504 - (void)name:(id)sender { [self _performResponderOperation:_cmd with:sender]; } |
|
3505 |
|
3506 FOR_EACH_RESPONDER_SELECTOR(FORWARD) |
|
3507 |
|
3508 - (void)insertText:(NSString *)text |
|
3509 { |
|
3510 [self _performResponderOperation:_cmd with:text]; |
|
3511 } |
|
3512 |
|
3513 @end |
|
3514 |
|
3515 @implementation WebView (WebViewEditingInMail) |
|
3516 |
|
3517 - (void)_insertNewlineInQuotedContent; |
|
3518 { |
|
3519 [[self _bridgeForSelectedOrMainFrame] insertParagraphSeparatorInQuotedContent]; |
|
3520 } |
|
3521 |
|
3522 - (void)_replaceSelectionWithNode:(DOMNode *)node matchStyle:(BOOL)matchStyle |
|
3523 { |
|
3524 [[self _bridgeForSelectedOrMainFrame] replaceSelectionWithNode:node selectReplacement:YES smartReplace:NO matchStyle:matchStyle]; |
|
3525 } |
|
3526 |
|
3527 @end |
|
3528 |
|
3529 static WebFrameView *containingFrameView(NSView *view) |
|
3530 { |
|
3531 while (view && ![view isKindOfClass:[WebFrameView class]]) |
|
3532 view = [view superview]; |
|
3533 return (WebFrameView *)view; |
|
3534 } |
|
3535 |
|
3536 @implementation WebView (WebFileInternal) |
|
3537 |
|
3538 + (void)_setCacheModel:(WebCacheModel)cacheModel |
|
3539 { |
|
3540 if (s_didSetCacheModel && cacheModel == s_cacheModel) |
|
3541 return; |
|
3542 |
|
3543 NSString *nsurlCacheDirectory = [(NSString *)WKCopyFoundationCacheDirectory() autorelease]; |
|
3544 if (!nsurlCacheDirectory) |
|
3545 nsurlCacheDirectory = NSHomeDirectory(); |
|
3546 |
|
3547 // As a fudge factor, use 1000 instead of 1024, in case the reported byte |
|
3548 // count doesn't align exactly to a megabyte boundary. |
|
3549 vm_size_t memSize = WebMemorySize() / 1024 / 1000; |
|
3550 unsigned long long diskFreeSize = WebVolumeFreeSize(nsurlCacheDirectory) / 1024 / 1000; |
|
3551 NSURLCache *nsurlCache = [NSURLCache sharedURLCache]; |
|
3552 |
|
3553 unsigned cacheTotalCapacity = 0; |
|
3554 unsigned cacheMinDeadCapacity = 0; |
|
3555 unsigned cacheMaxDeadCapacity = 0; |
|
3556 |
|
3557 unsigned pageCacheCapacity = 0; |
|
3558 |
|
3559 NSUInteger nsurlCacheMemoryCapacity = 0; |
|
3560 NSUInteger nsurlCacheDiskCapacity = 0; |
|
3561 |
|
3562 switch (cacheModel) { |
|
3563 case WebCacheModelDocumentViewer: { |
|
3564 // Page cache capacity (in pages) |
|
3565 pageCacheCapacity = 0; |
|
3566 |
|
3567 // Object cache capacities (in bytes) |
|
3568 if (memSize >= 4096) |
|
3569 cacheTotalCapacity = 256 * 1024 * 1024; |
|
3570 else if (memSize >= 3072) |
|
3571 cacheTotalCapacity = 192 * 1024 * 1024; |
|
3572 else if (memSize >= 2048) |
|
3573 cacheTotalCapacity = 128 * 1024 * 1024; |
|
3574 else if (memSize >= 1536) |
|
3575 cacheTotalCapacity = 86 * 1024 * 1024; |
|
3576 else if (memSize >= 1024) |
|
3577 cacheTotalCapacity = 64 * 1024 * 1024; |
|
3578 else if (memSize >= 512) |
|
3579 cacheTotalCapacity = 32 * 1024 * 1024; |
|
3580 else if (memSize >= 256) |
|
3581 cacheTotalCapacity = 16 * 1024 * 1024; |
|
3582 |
|
3583 cacheMinDeadCapacity = 0; |
|
3584 cacheMaxDeadCapacity = 0; |
|
3585 |
|
3586 // Foundation memory cache capacity (in bytes) |
|
3587 nsurlCacheMemoryCapacity = 0; |
|
3588 |
|
3589 // Foundation disk cache capacity (in bytes) |
|
3590 nsurlCacheDiskCapacity = [nsurlCache diskCapacity]; |
|
3591 |
|
3592 break; |
|
3593 } |
|
3594 case WebCacheModelDocumentBrowser: { |
|
3595 // Page cache capacity (in pages) |
|
3596 if (memSize >= 1024) |
|
3597 pageCacheCapacity = 3; |
|
3598 else if (memSize >= 512) |
|
3599 pageCacheCapacity = 2; |
|
3600 else if (memSize >= 256) |
|
3601 pageCacheCapacity = 1; |
|
3602 else |
|
3603 pageCacheCapacity = 0; |
|
3604 |
|
3605 // Object cache capacities (in bytes) |
|
3606 if (memSize >= 4096) |
|
3607 cacheTotalCapacity = 256 * 1024 * 1024; |
|
3608 else if (memSize >= 3072) |
|
3609 cacheTotalCapacity = 192 * 1024 * 1024; |
|
3610 else if (memSize >= 2048) |
|
3611 cacheTotalCapacity = 128 * 1024 * 1024; |
|
3612 else if (memSize >= 1536) |
|
3613 cacheTotalCapacity = 86 * 1024 * 1024; |
|
3614 else if (memSize >= 1024) |
|
3615 cacheTotalCapacity = 64 * 1024 * 1024; |
|
3616 else if (memSize >= 512) |
|
3617 cacheTotalCapacity = 32 * 1024 * 1024; |
|
3618 else if (memSize >= 256) |
|
3619 cacheTotalCapacity = 16 * 1024 * 1024; |
|
3620 |
|
3621 cacheMinDeadCapacity = cacheTotalCapacity / 8; |
|
3622 cacheMaxDeadCapacity = cacheTotalCapacity / 4; |
|
3623 |
|
3624 // Foundation memory cache capacity (in bytes) |
|
3625 if (memSize >= 2048) |
|
3626 nsurlCacheMemoryCapacity = 4 * 1024 * 1024; |
|
3627 else if (memSize >= 1024) |
|
3628 nsurlCacheMemoryCapacity = 2 * 1024 * 1024; |
|
3629 else if (memSize >= 512) |
|
3630 nsurlCacheMemoryCapacity = 1 * 1024 * 1024; |
|
3631 else |
|
3632 nsurlCacheMemoryCapacity = 512 * 1024; |
|
3633 |
|
3634 // Foundation disk cache capacity (in bytes) |
|
3635 if (diskFreeSize >= 16384) |
|
3636 nsurlCacheDiskCapacity = 50 * 1024 * 1024; |
|
3637 else if (diskFreeSize >= 8192) |
|
3638 nsurlCacheDiskCapacity = 40 * 1024 * 1024; |
|
3639 else if (diskFreeSize >= 4096) |
|
3640 nsurlCacheDiskCapacity = 30 * 1024 * 1024; |
|
3641 else |
|
3642 nsurlCacheDiskCapacity = 20 * 1024 * 1024; |
|
3643 |
|
3644 break; |
|
3645 } |
|
3646 case WebCacheModelPrimaryWebBrowser: { |
|
3647 // Page cache capacity (in pages) |
|
3648 // (Research indicates that value / page drops substantially after 3 pages.) |
|
3649 if (memSize >= 8192) |
|
3650 pageCacheCapacity = 7; |
|
3651 if (memSize >= 4096) |
|
3652 pageCacheCapacity = 6; |
|
3653 else if (memSize >= 2048) |
|
3654 pageCacheCapacity = 5; |
|
3655 else if (memSize >= 1024) |
|
3656 pageCacheCapacity = 4; |
|
3657 else if (memSize >= 512) |
|
3658 pageCacheCapacity = 3; |
|
3659 else if (memSize >= 256) |
|
3660 pageCacheCapacity = 2; |
|
3661 else |
|
3662 pageCacheCapacity = 1; |
|
3663 |
|
3664 // Object cache capacities (in bytes) |
|
3665 // (Testing indicates that value / MB depends heavily on content and |
|
3666 // browsing pattern. Even growth above 128MB can have substantial |
|
3667 // value / MB for some content / browsing patterns.) |
|
3668 if (memSize >= 4096) |
|
3669 cacheTotalCapacity = 512 * 1024 * 1024; |
|
3670 else if (memSize >= 3072) |
|
3671 cacheTotalCapacity = 384 * 1024 * 1024; |
|
3672 else if (memSize >= 2048) |
|
3673 cacheTotalCapacity = 256 * 1024 * 1024; |
|
3674 else if (memSize >= 1536) |
|
3675 cacheTotalCapacity = 172 * 1024 * 1024; |
|
3676 else if (memSize >= 1024) |
|
3677 cacheTotalCapacity = 128 * 1024 * 1024; |
|
3678 else if (memSize >= 512) |
|
3679 cacheTotalCapacity = 64 * 1024 * 1024; |
|
3680 else if (memSize >= 256) |
|
3681 cacheTotalCapacity = 32 * 1024 * 1024; |
|
3682 |
|
3683 cacheMinDeadCapacity = cacheTotalCapacity / 4; |
|
3684 cacheMaxDeadCapacity = cacheTotalCapacity / 2; |
|
3685 |
|
3686 // This code is here to avoid a PLT regression. We can remove it if we |
|
3687 // can prove that the overall system gain would justify the regression. |
|
3688 cacheMaxDeadCapacity = max(24u, cacheMaxDeadCapacity); |
|
3689 |
|
3690 // Foundation memory cache capacity (in bytes) |
|
3691 // (These values are small because WebCore does most caching itself.) |
|
3692 if (memSize >= 1024) |
|
3693 nsurlCacheMemoryCapacity = 4 * 1024 * 1024; |
|
3694 else if (memSize >= 512) |
|
3695 nsurlCacheMemoryCapacity = 2 * 1024 * 1024; |
|
3696 else if (memSize >= 256) |
|
3697 nsurlCacheMemoryCapacity = 1 * 1024 * 1024; |
|
3698 else |
|
3699 nsurlCacheMemoryCapacity = 512 * 1024; |
|
3700 |
|
3701 // Foundation disk cache capacity (in bytes) |
|
3702 if (diskFreeSize >= 16384) |
|
3703 nsurlCacheDiskCapacity = 175 * 1024 * 1024; |
|
3704 else if (diskFreeSize >= 8192) |
|
3705 nsurlCacheDiskCapacity = 150 * 1024 * 1024; |
|
3706 else if (diskFreeSize >= 4096) |
|
3707 nsurlCacheDiskCapacity = 125 * 1024 * 1024; |
|
3708 else if (diskFreeSize >= 2048) |
|
3709 nsurlCacheDiskCapacity = 100 * 1024 * 1024; |
|
3710 else if (diskFreeSize >= 1024) |
|
3711 nsurlCacheDiskCapacity = 75 * 1024 * 1024; |
|
3712 else |
|
3713 nsurlCacheDiskCapacity = 50 * 1024 * 1024; |
|
3714 |
|
3715 break; |
|
3716 } |
|
3717 default: |
|
3718 ASSERT_NOT_REACHED(); |
|
3719 }; |
|
3720 |
|
3721 #ifdef BUILDING_ON_TIGER |
|
3722 // Don't use a big Foundation disk cache on Tiger because, according to the |
|
3723 // PLT, the Foundation disk cache on Tiger is slower than the network. |
|
3724 nsurlCacheDiskCapacity = [[NSURLCache sharedURLCache] diskCapacity]; |
|
3725 #else |
|
3726 // Don't use a big Foundation disk cache on older versions of Leopard because |
|
3727 // doing so causes a SPOD on launch (<rdar://problem/5465260>). |
|
3728 if (NSVersionOfRunTimeLibrary("CFNetwork") < WEBKIT_FIRST_CFNETWORK_VERSION_WITH_LARGE_DISK_CACHE_FIX) |
|
3729 nsurlCacheDiskCapacity = [[NSURLCache sharedURLCache] diskCapacity]; |
|
3730 #endif |
|
3731 |
|
3732 // Don't shrink a big disk cache, since that would cause churn. |
|
3733 nsurlCacheDiskCapacity = max(nsurlCacheDiskCapacity, [nsurlCache diskCapacity]); |
|
3734 |
|
3735 cache()->setCapacities(cacheMinDeadCapacity, cacheMaxDeadCapacity, cacheTotalCapacity); |
|
3736 pageCache()->setCapacity(pageCacheCapacity); |
|
3737 [nsurlCache setMemoryCapacity:nsurlCacheMemoryCapacity]; |
|
3738 [nsurlCache setDiskCapacity:nsurlCacheDiskCapacity]; |
|
3739 |
|
3740 s_cacheModel = cacheModel; |
|
3741 s_didSetCacheModel = YES; |
|
3742 } |
|
3743 |
|
3744 + (WebCacheModel)_cacheModel |
|
3745 { |
|
3746 return s_cacheModel; |
|
3747 } |
|
3748 |
|
3749 + (WebCacheModel)_didSetCacheModel |
|
3750 { |
|
3751 return s_didSetCacheModel; |
|
3752 } |
|
3753 |
|
3754 + (WebCacheModel)_maxCacheModelInAnyInstance |
|
3755 { |
|
3756 WebCacheModel cacheModel = WebCacheModelDocumentViewer; |
|
3757 NSEnumerator *enumerator = [(NSMutableSet *)allWebViewsSet objectEnumerator]; |
|
3758 while (WebPreferences *preferences = [[enumerator nextObject] preferences]) |
|
3759 cacheModel = max(cacheModel, [preferences cacheModel]); |
|
3760 return cacheModel; |
|
3761 } |
|
3762 |
|
3763 + (void)_preferencesChangedNotification:(NSNotification *)notification |
|
3764 { |
|
3765 WebPreferences *preferences = (WebPreferences *)[notification object]; |
|
3766 ASSERT([preferences isKindOfClass:[WebPreferences class]]); |
|
3767 |
|
3768 WebCacheModel cacheModel = [preferences cacheModel]; |
|
3769 if (![self _didSetCacheModel] || cacheModel > [self _cacheModel]) |
|
3770 [self _setCacheModel:cacheModel]; |
|
3771 else if (cacheModel < [self _cacheModel]) |
|
3772 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])]; |
|
3773 } |
|
3774 |
|
3775 + (void)_preferencesRemovedNotification:(NSNotification *)notification |
|
3776 { |
|
3777 WebPreferences *preferences = (WebPreferences *)[notification object]; |
|
3778 ASSERT([preferences isKindOfClass:[WebPreferences class]]); |
|
3779 |
|
3780 if ([preferences cacheModel] == [self _cacheModel]) |
|
3781 [self _setCacheModel:max([[WebPreferences standardPreferences] cacheModel], [self _maxCacheModelInAnyInstance])]; |
|
3782 } |
|
3783 |
|
3784 - (WebFrame *)_focusedFrame |
|
3785 { |
|
3786 NSResponder *resp = [[self window] firstResponder]; |
|
3787 if (resp && [resp isKindOfClass:[NSView class]] && [(NSView *)resp isDescendantOf:[[self mainFrame] frameView]]) { |
|
3788 WebFrameView *frameView = containingFrameView((NSView *)resp); |
|
3789 ASSERT(frameView != nil); |
|
3790 return [frameView webFrame]; |
|
3791 } |
|
3792 |
|
3793 return nil; |
|
3794 } |
|
3795 |
|
3796 - (WebFrame *)_selectedOrMainFrame |
|
3797 { |
|
3798 WebFrame *result = [self selectedFrame]; |
|
3799 if (result == nil) |
|
3800 result = [self mainFrame]; |
|
3801 return result; |
|
3802 } |
|
3803 |
|
3804 - (WebFrameBridge *)_bridgeForSelectedOrMainFrame |
|
3805 { |
|
3806 return [[self _selectedOrMainFrame] _bridge]; |
|
3807 } |
|
3808 |
|
3809 - (BOOL)_isLoading |
|
3810 { |
|
3811 WebFrame *mainFrame = [self mainFrame]; |
|
3812 return [[mainFrame _dataSource] isLoading] |
|
3813 || [[mainFrame provisionalDataSource] isLoading]; |
|
3814 } |
|
3815 |
|
3816 - (WebFrameView *)_frameViewAtWindowPoint:(NSPoint)point |
|
3817 { |
|
3818 if (_private->closed) |
|
3819 return nil; |
|
3820 NSView *view = [self hitTest:[[self superview] convertPoint:point fromView:nil]]; |
|
3821 if (![view isDescendantOf:[[self mainFrame] frameView]]) |
|
3822 return nil; |
|
3823 WebFrameView *frameView = containingFrameView(view); |
|
3824 ASSERT(frameView); |
|
3825 return frameView; |
|
3826 } |
|
3827 |
|
3828 + (void)_preflightSpellCheckerNow:(id)sender |
|
3829 { |
|
3830 [[NSSpellChecker sharedSpellChecker] _preflightChosenSpellServer]; |
|
3831 } |
|
3832 |
|
3833 + (void)_preflightSpellChecker |
|
3834 { |
|
3835 // As AppKit does, we wish to delay tickling the shared spellchecker into existence on application launch. |
|
3836 if ([NSSpellChecker sharedSpellCheckerExists]) { |
|
3837 [self _preflightSpellCheckerNow:self]; |
|
3838 } else { |
|
3839 [self performSelector:@selector(_preflightSpellCheckerNow:) withObject:self afterDelay:2.0]; |
|
3840 } |
|
3841 } |
|
3842 |
|
3843 - (BOOL)_continuousCheckingAllowed |
|
3844 { |
|
3845 static BOOL allowContinuousSpellChecking = YES; |
|
3846 static BOOL readAllowContinuousSpellCheckingDefault = NO; |
|
3847 if (!readAllowContinuousSpellCheckingDefault) { |
|
3848 if ([[NSUserDefaults standardUserDefaults] objectForKey:@"NSAllowContinuousSpellChecking"]) { |
|
3849 allowContinuousSpellChecking = [[NSUserDefaults standardUserDefaults] boolForKey:@"NSAllowContinuousSpellChecking"]; |
|
3850 } |
|
3851 readAllowContinuousSpellCheckingDefault = YES; |
|
3852 } |
|
3853 return allowContinuousSpellChecking; |
|
3854 } |
|
3855 |
|
3856 - (NSResponder *)_responderForResponderOperations |
|
3857 { |
|
3858 NSResponder *responder = [[self window] firstResponder]; |
|
3859 WebFrameView *mainFrameView = [[self mainFrame] frameView]; |
|
3860 |
|
3861 // If the current responder is outside of the webview, use our main frameView or its |
|
3862 // document view. We also do this for subviews of self that are siblings of the main |
|
3863 // frameView since clients might insert non-webview-related views there (see 4552713). |
|
3864 if (responder != self && ![mainFrameView _web_firstResponderIsSelfOrDescendantView]) { |
|
3865 responder = [mainFrameView documentView]; |
|
3866 if (!responder) |
|
3867 responder = mainFrameView; |
|
3868 } |
|
3869 return responder; |
|
3870 } |
|
3871 |
|
3872 - (void)_openFrameInNewWindowFromMenu:(NSMenuItem *)sender |
|
3873 { |
|
3874 ASSERT_ARG(sender, [sender isKindOfClass:[NSMenuItem class]]); |
|
3875 |
|
3876 NSDictionary *element = [sender representedObject]; |
|
3877 ASSERT([element isKindOfClass:[NSDictionary class]]); |
|
3878 |
|
3879 NSURLRequest *request = [[[[element objectForKey:WebElementFrameKey] dataSource] request] copy]; |
|
3880 ASSERT(request); |
|
3881 |
|
3882 [self _openNewWindowWithRequest:request]; |
|
3883 [request release]; |
|
3884 } |
|
3885 |
|
3886 - (void)_searchWithGoogleFromMenu:(id)sender |
|
3887 { |
|
3888 id documentView = [[[self selectedFrame] frameView] documentView]; |
|
3889 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) { |
|
3890 return; |
|
3891 } |
|
3892 |
|
3893 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString]; |
|
3894 if ([selectedString length] == 0) { |
|
3895 return; |
|
3896 } |
|
3897 |
|
3898 NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; |
|
3899 [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; |
|
3900 NSMutableString *s = [selectedString mutableCopy]; |
|
3901 const unichar nonBreakingSpaceCharacter = 0xA0; |
|
3902 NSString *nonBreakingSpaceString = [NSString stringWithCharacters:&nonBreakingSpaceCharacter length:1]; |
|
3903 [s replaceOccurrencesOfString:nonBreakingSpaceString withString:@" " options:0 range:NSMakeRange(0, [s length])]; |
|
3904 [pasteboard setString:s forType:NSStringPboardType]; |
|
3905 [s release]; |
|
3906 |
|
3907 // FIXME: seems fragile to use the service by name, but this is what AppKit does |
|
3908 NSPerformService(@"Search With Google", pasteboard); |
|
3909 } |
|
3910 |
|
3911 - (void)_searchWithSpotlightFromMenu:(id)sender |
|
3912 { |
|
3913 id documentView = [[[self selectedFrame] frameView] documentView]; |
|
3914 if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) { |
|
3915 return; |
|
3916 } |
|
3917 |
|
3918 NSString *selectedString = [(id <WebDocumentText>)documentView selectedString]; |
|
3919 if ([selectedString length] == 0) { |
|
3920 return; |
|
3921 } |
|
3922 |
|
3923 (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions); |
|
3924 } |
|
3925 |
|
3926 // Slightly funky method that lets us have one copy of the logic for finding docViews that can do |
|
3927 // text sizing. It returns whether it found any "suitable" doc views. It sends sel to any suitable |
|
3928 // doc views, or if sel==0 we do nothing to them. For doc views that track our size factor, they are |
|
3929 // suitable if doTrackingViews==YES (which in practice means that our size factor isn't at its max or |
|
3930 // min). For doc views that don't track it, we send them testSel to determine suitablility. If we |
|
3931 // do find any suitable tracking doc views and newScaleFactor!=0, we will set the common scale factor |
|
3932 // to that new factor before we send sel to any of them. |
|
3933 - (BOOL)_performTextSizingSelector:(SEL)sel withObject:(id)arg onTrackingDocs:(BOOL)doTrackingViews selForNonTrackingDocs:(SEL)testSel newScaleFactor:(float)newScaleFactor |
|
3934 { |
|
3935 if ([[self mainFrame] _dataSource] == nil) |
|
3936 return NO; |
|
3937 |
|
3938 BOOL foundSome = NO; |
|
3939 NSArray *docViews = [[self mainFrame] _documentViews]; |
|
3940 for (int i = [docViews count]-1; i >= 0; i--) { |
|
3941 id docView = [docViews objectAtIndex:i]; |
|
3942 if ([docView conformsToProtocol:@protocol(_WebDocumentTextSizing)]) { |
|
3943 id <_WebDocumentTextSizing> sizingDocView = (id <_WebDocumentTextSizing>)docView; |
|
3944 BOOL isSuitable; |
|
3945 if ([sizingDocView _tracksCommonSizeFactor]) { |
|
3946 isSuitable = doTrackingViews; |
|
3947 if (isSuitable && newScaleFactor != 0) |
|
3948 _private->textSizeMultiplier = newScaleFactor; |
|
3949 } else { |
|
3950 // Incantation to perform a selector returning a BOOL. |
|
3951 isSuitable = ((BOOL(*)(id, SEL))objc_msgSend)(sizingDocView, testSel); |
|
3952 } |
|
3953 |
|
3954 if (isSuitable) { |
|
3955 if (sel != 0) { |
|
3956 foundSome = YES; |
|
3957 [sizingDocView performSelector:sel withObject:arg]; |
|
3958 } else { |
|
3959 // if we're just called for the benefit of the return value, we can return at first match |
|
3960 return YES; |
|
3961 } |
|
3962 } |
|
3963 } |
|
3964 } |
|
3965 |
|
3966 return foundSome; |
|
3967 } |
|
3968 |
|
3969 - (void)_notifyTextSizeMultiplierChanged |
|
3970 { |
|
3971 if ([[self mainFrame] _dataSource] == nil) |
|
3972 return; |
|
3973 |
|
3974 NSArray *docViews = [[self mainFrame] _documentViews]; |
|
3975 for (int i = [docViews count]-1; i >= 0; i--) { |
|
3976 id docView = [docViews objectAtIndex:i]; |
|
3977 if ([docView conformsToProtocol:@protocol(_WebDocumentTextSizing)] == NO) |
|
3978 continue; |
|
3979 |
|
3980 id <_WebDocumentTextSizing> sizingDocView = (id <_WebDocumentTextSizing>)docView; |
|
3981 if ([sizingDocView _tracksCommonSizeFactor]) |
|
3982 [sizingDocView _textSizeMultiplierChanged]; |
|
3983 } |
|
3984 |
|
3985 } |
|
3986 |
|
3987 @end |
|
3988 |
|
3989 @implementation WebView (WebViewInternal) |
|
3990 |
|
3991 - (BOOL)_becomingFirstResponderFromOutside |
|
3992 { |
|
3993 return _private->becomingFirstResponderFromOutside; |
|
3994 } |
|
3995 |
|
3996 - (void)_receivedIconChangedNotification:(NSNotification *)notification |
|
3997 { |
|
3998 // Get the URL for this notification |
|
3999 NSDictionary *userInfo = [notification userInfo]; |
|
4000 ASSERT([userInfo isKindOfClass:[NSDictionary class]]); |
|
4001 NSString *urlString = [userInfo objectForKey:WebIconNotificationUserInfoURLKey]; |
|
4002 ASSERT([urlString isKindOfClass:[NSString class]]); |
|
4003 |
|
4004 // If that URL matches the current main frame, dispatch the delegate call, which will also unregister |
|
4005 // us for this notification |
|
4006 if ([[self mainFrameURL] isEqualTo:urlString]) |
|
4007 [self _dispatchDidReceiveIconFromWebFrame:[self mainFrame]]; |
|
4008 } |
|
4009 |
|
4010 - (void)_registerForIconNotification:(BOOL)listen |
|
4011 { |
|
4012 if (listen) |
|
4013 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_receivedIconChangedNotification:) name:WebIconDatabaseDidAddIconNotification object:nil]; |
|
4014 else |
|
4015 [[NSNotificationCenter defaultCenter] removeObserver:self name:WebIconDatabaseDidAddIconNotification object:nil]; |
|
4016 } |
|
4017 |
|
4018 - (void)_dispatchDidReceiveIconFromWebFrame:(WebFrame *)webFrame |
|
4019 { |
|
4020 // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now. |
|
4021 [self _willChangeValueForKey:_WebMainFrameIconKey]; |
|
4022 |
|
4023 // Since we definitely have an icon and are about to send out the delegate call for that, this WebView doesn't need to listen for the general |
|
4024 // notification any longer |
|
4025 [self _registerForIconNotification:NO]; |
|
4026 |
|
4027 WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(self); |
|
4028 if (implementations.didReceiveIconForFrameFunc) { |
|
4029 Image* image = iconDatabase()->iconForPageURL(core(webFrame)->loader()->url().url(), IntSize(16, 16)); |
|
4030 if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16))) |
|
4031 CallFrameLoadDelegate(implementations.didReceiveIconForFrameFunc, self, @selector(webView:didReceiveIcon:forFrame:), icon, webFrame); |
|
4032 } |
|
4033 |
|
4034 [self _didChangeValueForKey:_WebMainFrameIconKey]; |
|
4035 } |
|
4036 |
|
4037 - (NSString *)_userVisibleBundleVersionFromFullVersion:(NSString *)fullVersion |
|
4038 { |
|
4039 // If the version is 4 digits long or longer, then the first digit represents |
|
4040 // the version of the OS. Our user agent string should not include this first digit, |
|
4041 // so strip it off and report the rest as the version. <rdar://problem/4997547> |
|
4042 NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]; |
|
4043 if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4) |
|
4044 return [fullVersion substringFromIndex:1]; |
|
4045 if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4) |
|
4046 return [fullVersion substringFromIndex:1]; |
|
4047 return fullVersion; |
|
4048 } |
|
4049 |
|
4050 - (NSString *)_userAgentWithApplicationName:(NSString *)applicationName andWebKitVersion:(NSString *)version |
|
4051 { |
|
4052 NSString *language = [NSUserDefaults _webkit_preferredLanguageCode]; |
|
4053 if ([applicationName length]) |
|
4054 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko) %@", language, version, applicationName]; |
|
4055 return [NSString stringWithFormat:@"Mozilla/5.0 (Macintosh; U; " PROCESSOR " Mac OS X; %@) AppleWebKit/%@ (KHTML, like Gecko)", language, version]; |
|
4056 } |
|
4057 |
|
4058 // Get the appropriate user-agent string for a particular URL. |
|
4059 - (WebCore::String)_userAgentForURL:(const WebCore::KURL&)url |
|
4060 { |
|
4061 if (_private->useSiteSpecificSpoofing) { |
|
4062 // FIXME: Make this a hash table lookup if more domains need spoofing. |
|
4063 // FIXME: Remove yahoo.com once <rdar://problem/5057117> is fixed. |
|
4064 if (url.host().endsWith("yahoo.com")) { |
|
4065 static String yahooUserAgent([self _userAgentWithApplicationName:_private->applicationNameForUserAgent andWebKitVersion:@"422"]); |
|
4066 return yahooUserAgent; |
|
4067 } |
|
4068 |
|
4069 // FIXME: Remove flickr.com workaround once <rdar://problem/5084872> is fixed |
|
4070 if (url.host().endsWith("flickr.com")) { |
|
4071 // Safari 2.0.4's user agent string works here |
|
4072 static String safari204UserAgent([self _userAgentWithApplicationName:@"Safari/419.3" andWebKitVersion:@"419"]); |
|
4073 return safari204UserAgent; |
|
4074 } |
|
4075 } |
|
4076 |
|
4077 if (_private->userAgent->isNull()) { |
|
4078 NSString *sourceVersion = [[NSBundle bundleForClass:[WebView class]] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; |
|
4079 sourceVersion = [self _userVisibleBundleVersionFromFullVersion:sourceVersion]; |
|
4080 *_private->userAgent = [self _userAgentWithApplicationName:_private->applicationNameForUserAgent andWebKitVersion:sourceVersion]; |
|
4081 } |
|
4082 |
|
4083 return *_private->userAgent; |
|
4084 } |
|
4085 |
|
4086 - (void)_addObject:(id)object forIdentifier:(unsigned long)identifier |
|
4087 { |
|
4088 ASSERT(!_private->identifierMap->contains(identifier)); |
|
4089 |
|
4090 // If the identifier map is initially empty it means we're starting a load |
|
4091 // of something. The semantic is that the web view should be around as long |
|
4092 // as something is loading. Because of that we retain the web view. |
|
4093 if (_private->identifierMap->isEmpty()) |
|
4094 CFRetain(self); |
|
4095 |
|
4096 _private->identifierMap->set(identifier, object); |
|
4097 } |
|
4098 |
|
4099 - (id)_objectForIdentifier:(unsigned long)identifier |
|
4100 { |
|
4101 return _private->identifierMap->get(identifier).get(); |
|
4102 } |
|
4103 |
|
4104 - (void)_removeObjectForIdentifier:(unsigned long)identifier |
|
4105 { |
|
4106 HashMap<unsigned long, RetainPtr<id> >::iterator it = _private->identifierMap->find(identifier); |
|
4107 |
|
4108 // FIXME: This is currently needed because of a bug that causes didFail to be sent twice |
|
4109 // sometimes, see <rdar://problem/5009627> for more information. |
|
4110 if (it == _private->identifierMap->end()) |
|
4111 return; |
|
4112 |
|
4113 _private->identifierMap->remove(it); |
|
4114 |
|
4115 // If the identifier map is now empty it means we're no longer loading anything |
|
4116 // and we should release the web view. |
|
4117 if (_private->identifierMap->isEmpty()) |
|
4118 CFRelease(self); |
|
4119 } |
|
4120 |
|
4121 @end |
|
4122 |
|
4123 // We use these functions to call the delegates and block exceptions. These functions are |
|
4124 // declared inside a WebView category to get direct access to the delegate data memebers, |
|
4125 // preventing more ObjC message dispatch and compensating for the expense of the @try/@catch. |
|
4126 |
|
4127 @implementation WebView (WebCallDelegateFunctions) |
|
4128 |
|
4129 #if !(defined(__i386__) || defined(__x86_64__)) |
|
4130 typedef double (*ObjCMsgSendFPRet)(id, SEL, ...); |
|
4131 static const ObjCMsgSendFPRet objc_msgSend_fpret = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend); |
|
4132 #endif |
|
4133 |
|
4134 static inline id CallDelegate(WebView *self, id delegate, SEL selector) |
|
4135 { |
|
4136 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4137 return nil; |
|
4138 if (!self->_private->catchesDelegateExceptions) |
|
4139 return objc_msgSend(delegate, selector, self); |
|
4140 @try { |
|
4141 return objc_msgSend(delegate, selector, self); |
|
4142 } @catch(id exception) { |
|
4143 ReportDiscardedDelegateException(selector, exception); |
|
4144 } |
|
4145 return nil; |
|
4146 } |
|
4147 |
|
4148 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object) |
|
4149 { |
|
4150 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4151 return nil; |
|
4152 if (!self->_private->catchesDelegateExceptions) |
|
4153 return objc_msgSend(delegate, selector, self, object); |
|
4154 @try { |
|
4155 return objc_msgSend(delegate, selector, self, object); |
|
4156 } @catch(id exception) { |
|
4157 ReportDiscardedDelegateException(selector, exception); |
|
4158 } |
|
4159 return nil; |
|
4160 } |
|
4161 |
|
4162 static inline id CallDelegate(WebView *self, id delegate, SEL selector, NSRect rect) |
|
4163 { |
|
4164 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4165 return nil; |
|
4166 if (!self->_private->catchesDelegateExceptions) |
|
4167 return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect); |
|
4168 @try { |
|
4169 return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect); |
|
4170 } @catch(id exception) { |
|
4171 ReportDiscardedDelegateException(selector, exception); |
|
4172 } |
|
4173 return nil; |
|
4174 } |
|
4175 |
|
4176 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2) |
|
4177 { |
|
4178 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4179 return nil; |
|
4180 if (!self->_private->catchesDelegateExceptions) |
|
4181 return objc_msgSend(delegate, selector, self, object1, object2); |
|
4182 @try { |
|
4183 return objc_msgSend(delegate, selector, self, object1, object2); |
|
4184 } @catch(id exception) { |
|
4185 ReportDiscardedDelegateException(selector, exception); |
|
4186 } |
|
4187 return nil; |
|
4188 } |
|
4189 |
|
4190 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, BOOL boolean) |
|
4191 { |
|
4192 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4193 return nil; |
|
4194 if (!self->_private->catchesDelegateExceptions) |
|
4195 return objc_msgSend(delegate, selector, self, object, boolean); |
|
4196 @try { |
|
4197 return objc_msgSend(delegate, selector, self, object, boolean); |
|
4198 } @catch(id exception) { |
|
4199 ReportDiscardedDelegateException(selector, exception); |
|
4200 } |
|
4201 return nil; |
|
4202 } |
|
4203 |
|
4204 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2, id object3) |
|
4205 { |
|
4206 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4207 return nil; |
|
4208 if (!self->_private->catchesDelegateExceptions) |
|
4209 return objc_msgSend(delegate, selector, self, object1, object2, object3); |
|
4210 @try { |
|
4211 return objc_msgSend(delegate, selector, self, object1, object2, object3); |
|
4212 } @catch(id exception) { |
|
4213 ReportDiscardedDelegateException(selector, exception); |
|
4214 } |
|
4215 return nil; |
|
4216 } |
|
4217 |
|
4218 static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, NSUInteger integer) |
|
4219 { |
|
4220 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4221 return nil; |
|
4222 if (!self->_private->catchesDelegateExceptions) |
|
4223 return objc_msgSend(delegate, selector, self, object, integer); |
|
4224 @try { |
|
4225 return objc_msgSend(delegate, selector, self, object, integer); |
|
4226 } @catch(id exception) { |
|
4227 ReportDiscardedDelegateException(selector, exception); |
|
4228 } |
|
4229 return nil; |
|
4230 } |
|
4231 |
|
4232 static inline float CallDelegateReturningFloat(WebView *self, id delegate, SEL selector) |
|
4233 { |
|
4234 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4235 return 0.0f; |
|
4236 if (!self->_private->catchesDelegateExceptions) |
|
4237 return static_cast<float>(objc_msgSend_fpret(delegate, selector, self)); |
|
4238 @try { |
|
4239 return static_cast<float>(objc_msgSend_fpret(delegate, selector, self)); |
|
4240 } @catch(id exception) { |
|
4241 ReportDiscardedDelegateException(selector, exception); |
|
4242 } |
|
4243 return 0.0f; |
|
4244 } |
|
4245 |
|
4246 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector) |
|
4247 { |
|
4248 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4249 return result; |
|
4250 if (!self->_private->catchesDelegateExceptions) |
|
4251 return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self); |
|
4252 @try { |
|
4253 return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self); |
|
4254 } @catch(id exception) { |
|
4255 ReportDiscardedDelegateException(selector, exception); |
|
4256 } |
|
4257 return result; |
|
4258 } |
|
4259 |
|
4260 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object) |
|
4261 { |
|
4262 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4263 return result; |
|
4264 if (!self->_private->catchesDelegateExceptions) |
|
4265 return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object); |
|
4266 @try { |
|
4267 return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object); |
|
4268 } @catch(id exception) { |
|
4269 ReportDiscardedDelegateException(selector, exception); |
|
4270 } |
|
4271 return result; |
|
4272 } |
|
4273 |
|
4274 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object, BOOL boolean) |
|
4275 { |
|
4276 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4277 return result; |
|
4278 if (!self->_private->catchesDelegateExceptions) |
|
4279 return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean); |
|
4280 @try { |
|
4281 return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean); |
|
4282 } @catch(id exception) { |
|
4283 ReportDiscardedDelegateException(selector, exception); |
|
4284 } |
|
4285 return result; |
|
4286 } |
|
4287 |
|
4288 static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object1, id object2) |
|
4289 { |
|
4290 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4291 return result; |
|
4292 if (!self->_private->catchesDelegateExceptions) |
|
4293 return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2); |
|
4294 @try { |
|
4295 return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2); |
|
4296 } @catch(id exception) { |
|
4297 ReportDiscardedDelegateException(selector, exception); |
|
4298 } |
|
4299 return result; |
|
4300 } |
|
4301 |
|
4302 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector) |
|
4303 { |
|
4304 if (!delegate) |
|
4305 return nil; |
|
4306 if (!self->_private->catchesDelegateExceptions) |
|
4307 return implementation(delegate, selector, self); |
|
4308 @try { |
|
4309 return implementation(delegate, selector, self); |
|
4310 } @catch(id exception) { |
|
4311 ReportDiscardedDelegateException(selector, exception); |
|
4312 } |
|
4313 return nil; |
|
4314 } |
|
4315 |
|
4316 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object) |
|
4317 { |
|
4318 if (!delegate) |
|
4319 return nil; |
|
4320 if (!self->_private->catchesDelegateExceptions) |
|
4321 return implementation(delegate, selector, self, object); |
|
4322 @try { |
|
4323 return implementation(delegate, selector, self, object); |
|
4324 } @catch(id exception) { |
|
4325 ReportDiscardedDelegateException(selector, exception); |
|
4326 } |
|
4327 return nil; |
|
4328 } |
|
4329 |
|
4330 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2) |
|
4331 { |
|
4332 if (!delegate) |
|
4333 return nil; |
|
4334 if (!self->_private->catchesDelegateExceptions) |
|
4335 return implementation(delegate, selector, self, object1, object2); |
|
4336 @try { |
|
4337 return implementation(delegate, selector, self, object1, object2); |
|
4338 } @catch(id exception) { |
|
4339 ReportDiscardedDelegateException(selector, exception); |
|
4340 } |
|
4341 return nil; |
|
4342 } |
|
4343 |
|
4344 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3) |
|
4345 { |
|
4346 if (!delegate) |
|
4347 return nil; |
|
4348 if (!self->_private->catchesDelegateExceptions) |
|
4349 return implementation(delegate, selector, self, object1, object2, object3); |
|
4350 @try { |
|
4351 return implementation(delegate, selector, self, object1, object2, object3); |
|
4352 } @catch(id exception) { |
|
4353 ReportDiscardedDelegateException(selector, exception); |
|
4354 } |
|
4355 return nil; |
|
4356 } |
|
4357 |
|
4358 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3, id object4) |
|
4359 { |
|
4360 if (!delegate) |
|
4361 return nil; |
|
4362 if (!self->_private->catchesDelegateExceptions) |
|
4363 return implementation(delegate, selector, self, object1, object2, object3, object4); |
|
4364 @try { |
|
4365 return implementation(delegate, selector, self, object1, object2, object3, object4); |
|
4366 } @catch(id exception) { |
|
4367 ReportDiscardedDelegateException(selector, exception); |
|
4368 } |
|
4369 return nil; |
|
4370 } |
|
4371 |
|
4372 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2) |
|
4373 { |
|
4374 if (!delegate) |
|
4375 return nil; |
|
4376 if (!self->_private->catchesDelegateExceptions) |
|
4377 return implementation(delegate, selector, self, object1, integer, object2); |
|
4378 @try { |
|
4379 return implementation(delegate, selector, self, object1, integer, object2); |
|
4380 } @catch(id exception) { |
|
4381 ReportDiscardedDelegateException(selector, exception); |
|
4382 } |
|
4383 return nil; |
|
4384 } |
|
4385 |
|
4386 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3) |
|
4387 { |
|
4388 if (!delegate) |
|
4389 return nil; |
|
4390 if (!self->_private->catchesDelegateExceptions) |
|
4391 return implementation(delegate, selector, self, object1, object2, integer, object3); |
|
4392 @try { |
|
4393 return implementation(delegate, selector, self, object1, object2, integer, object3); |
|
4394 } @catch(id exception) { |
|
4395 ReportDiscardedDelegateException(selector, exception); |
|
4396 } |
|
4397 return nil; |
|
4398 } |
|
4399 |
|
4400 static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3) |
|
4401 { |
|
4402 if (!delegate) |
|
4403 return nil; |
|
4404 if (!self->_private->catchesDelegateExceptions) |
|
4405 return implementation(delegate, selector, self, object1, interval, object2, object3); |
|
4406 @try { |
|
4407 return implementation(delegate, selector, self, object1, interval, object2, object3); |
|
4408 } @catch(id exception) { |
|
4409 ReportDiscardedDelegateException(selector, exception); |
|
4410 } |
|
4411 return nil; |
|
4412 } |
|
4413 |
|
4414 id CallUIDelegate(WebView *self, SEL selector) |
|
4415 { |
|
4416 return CallDelegate(self, self->_private->UIDelegate, selector); |
|
4417 } |
|
4418 |
|
4419 id CallUIDelegate(WebView *self, SEL selector, id object) |
|
4420 { |
|
4421 return CallDelegate(self, self->_private->UIDelegate, selector, object); |
|
4422 } |
|
4423 |
|
4424 id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean) |
|
4425 { |
|
4426 return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean); |
|
4427 } |
|
4428 |
|
4429 id CallUIDelegate(WebView *self, SEL selector, NSRect rect) |
|
4430 { |
|
4431 return CallDelegate(self, self->_private->UIDelegate, selector, rect); |
|
4432 } |
|
4433 |
|
4434 id CallUIDelegate(WebView *self, SEL selector, id object1, id object2) |
|
4435 { |
|
4436 return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2); |
|
4437 } |
|
4438 |
|
4439 id CallUIDelegate(WebView *self, SEL selector, id object1, id object2, id object3) |
|
4440 { |
|
4441 return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2, object3); |
|
4442 } |
|
4443 |
|
4444 id CallUIDelegate(WebView *self, SEL selector, id object, NSUInteger integer) |
|
4445 { |
|
4446 return CallDelegate(self, self->_private->UIDelegate, selector, object, integer); |
|
4447 } |
|
4448 |
|
4449 float CallUIDelegateReturningFloat(WebView *self, SEL selector) |
|
4450 { |
|
4451 return CallDelegateReturningFloat(self, self->_private->UIDelegate, selector); |
|
4452 } |
|
4453 |
|
4454 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector) |
|
4455 { |
|
4456 return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector); |
|
4457 } |
|
4458 |
|
4459 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object) |
|
4460 { |
|
4461 return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object); |
|
4462 } |
|
4463 |
|
4464 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean) |
|
4465 { |
|
4466 return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean); |
|
4467 } |
|
4468 |
|
4469 BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, id object2) |
|
4470 { |
|
4471 return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object1, object2); |
|
4472 } |
|
4473 |
|
4474 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector) |
|
4475 { |
|
4476 return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector); |
|
4477 } |
|
4478 |
|
4479 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object) |
|
4480 { |
|
4481 return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object); |
|
4482 } |
|
4483 |
|
4484 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2) |
|
4485 { |
|
4486 return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2); |
|
4487 } |
|
4488 |
|
4489 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3) |
|
4490 { |
|
4491 return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3); |
|
4492 } |
|
4493 |
|
4494 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4) |
|
4495 { |
|
4496 return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3, object4); |
|
4497 } |
|
4498 |
|
4499 id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSTimeInterval interval, id object2, id object3) |
|
4500 { |
|
4501 return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, interval, object2, object3); |
|
4502 } |
|
4503 |
|
4504 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2) |
|
4505 { |
|
4506 return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2); |
|
4507 } |
|
4508 |
|
4509 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3) |
|
4510 { |
|
4511 return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3); |
|
4512 } |
|
4513 |
|
4514 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4) |
|
4515 { |
|
4516 return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4); |
|
4517 } |
|
4518 |
|
4519 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2) |
|
4520 { |
|
4521 return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2); |
|
4522 } |
|
4523 |
|
4524 id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3) |
|
4525 { |
|
4526 return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3); |
|
4527 } |
|
4528 |
|
4529 // The form delegate needs to have it's own implementation, because the first argument is never the WebView |
|
4530 |
|
4531 id CallFormDelegate(WebView *self, SEL selector, id object1, id object2) |
|
4532 { |
|
4533 id delegate = self->_private->formDelegate; |
|
4534 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4535 return nil; |
|
4536 if (!self->_private->catchesDelegateExceptions) |
|
4537 return objc_msgSend(delegate, selector, object1, object2); |
|
4538 @try { |
|
4539 return objc_msgSend(delegate, selector, object1, object2); |
|
4540 } @catch(id exception) { |
|
4541 ReportDiscardedDelegateException(selector, exception); |
|
4542 } |
|
4543 return nil; |
|
4544 } |
|
4545 |
|
4546 id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5) |
|
4547 { |
|
4548 id delegate = self->_private->formDelegate; |
|
4549 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4550 return nil; |
|
4551 if (!self->_private->catchesDelegateExceptions) |
|
4552 return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5); |
|
4553 @try { |
|
4554 return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5); |
|
4555 } @catch(id exception) { |
|
4556 ReportDiscardedDelegateException(selector, exception); |
|
4557 } |
|
4558 return nil; |
|
4559 } |
|
4560 |
|
4561 BOOL CallFormDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, SEL selectorArg, id object2) |
|
4562 { |
|
4563 id delegate = self->_private->formDelegate; |
|
4564 if (!delegate || ![delegate respondsToSelector:selector]) |
|
4565 return result; |
|
4566 if (!self->_private->catchesDelegateExceptions) |
|
4567 return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2); |
|
4568 @try { |
|
4569 return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2); |
|
4570 } @catch(id exception) { |
|
4571 ReportDiscardedDelegateException(selector, exception); |
|
4572 } |
|
4573 return result; |
|
4574 } |
|
4575 |
|
4576 @end |