LayoutTests:
[WebKit-https.git] / WebCore / bridge / mac / FrameMac.mm
index 70c06a7..ff491ac 100644 (file)
@@ -26,7 +26,7 @@
 #import "config.h"
 #import "FrameMac.h"
 
-#import "AccessibilityObjectCache.h"
+#import "AXObjectCache.h"
 #import "BeforeUnloadEvent.h"
 #import "BlockExceptions.h"
 #import "BrowserExtensionMac.h"
 #import "HTMLFormElement.h"
 #import "HTMLFrameElement.h"
 #import "HTMLGenericFormElement.h"
+#import "HTMLInputElement.h"
 #import "HTMLNames.h"
 #import "HTMLTableCellElement.h"
-#import "KWQEditCommand.h"
-#import "KWQFormData.h"
-#import "KWQPageState.h"
+#import "WebCoreEditCommand.h"
+#import "FormDataMac.h"
+#import "WebCorePageState.h"
 #import "Logging.h"
 #import "MouseEventWithHitTestResults.h"
 #import "PlatformKeyboardEvent.h"
 #import "RenderTheme.h"
 #import "RenderView.h"
 #import "TextIterator.h"
-#import "TransferJob.h"
+#import "ResourceLoader.h"
 #import "WebCoreFrameBridge.h"
 #import "WebCoreViewFactory.h"
 #import "WebDashboardRegion.h"
+#import "WebScriptObjectPrivate.h"
 #import "csshelper.h"
+#import "htmlediting.h"
 #import "kjs_window.h"
 #import "visible_units.h"
+#import "WebCoreSystemInterface.h"
+#import <Carbon/Carbon.h>
 #import <JavaScriptCore/NP_jsobject.h>
-#import <JavaScriptCore/WebScriptObjectPrivate.h>
 #import <JavaScriptCore/npruntime_impl.h>
 
-#undef _KWQ_TIMING
+#undef _webcore_TIMING
 
 @interface NSObject (WebPlugIn)
 - (id)objectForWebScript;
-- (void *)pluginScriptableObject;
+- (NPObject *)createPluginScriptableObject;
 @end
 
 using namespace std;
 using namespace KJS::Bindings;
-using namespace KIO;
 
 using KJS::JSLock;
 using KJS::PausedTimeouts;
@@ -148,8 +151,8 @@ bool FrameView::isFrameView() const
     return true;
 }
 
-FrameMac::FrameMac(Page* page, RenderPart* ownerRenderer)
-    : Frame(page, ownerRenderer)
+FrameMac::FrameMac(Page* page, Element* ownerElement)
+    : Frame(page, ownerElement)
     , _bridge(nil)
     , _mouseDownView(nil)
     , _sendingEventToSubview(false)
@@ -170,7 +173,7 @@ FrameMac::~FrameMac()
     clearRecordedFormValues();    
     
     [_bridge clearFrame];
-    KWQRelease(_bridge);
+    HardRelease(_bridge);
     _bridge = nil;
 }
 
@@ -539,15 +542,15 @@ void FrameMac::redirectDataToPlugin(Widget* pluginWidget)
 }
 
 
-Frame* FrameMac::createFrame(const KURL& url, const String& name, RenderPart* renderer, const String& referrer)
+Frame* FrameMac::createFrame(const KURL& url, const String& name, Element* ownerElement, const String& referrer)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
     
     BOOL allowsScrolling = YES;
     int marginWidth = -1;
     int marginHeight = -1;
-    if (renderer->element()->hasTagName(frameTag) || renderer->element()->hasTagName(iframeTag)) {
-        HTMLFrameElement* o = static_cast<HTMLFrameElement*>(renderer->element());
+    if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
+        HTMLFrameElement* o = static_cast<HTMLFrameElement*>(ownerElement);
         allowsScrolling = o->scrollingMode() != ScrollBarAlwaysOff;
         marginWidth = o->getMarginWidth();
         marginHeight = o->getMarginHeight();
@@ -556,7 +559,7 @@ Frame* FrameMac::createFrame(const KURL& url, const String& name, RenderPart* re
     WebCoreFrameBridge *childBridge = [_bridge createChildFrameNamed:name
                                                              withURL:url.getNSURL()
                                                             referrer:referrer 
-                                                          renderPart:renderer
+                                                          ownerElement:ownerElement
                                                      allowsScrolling:allowsScrolling
                                                          marginWidth:marginWidth
                                                         marginHeight:marginHeight];
@@ -579,7 +582,7 @@ void FrameMac::setView(FrameView *view)
     // Delete old PlugIn data structures
     cleanupPluginRootObjects();
     _bindingRoot = 0;
-    KWQRelease(_windowScriptObject);
+    HardRelease(_windowScriptObject);
     _windowScriptObject = 0;
 
     if (_windowScriptNPObject) {
@@ -611,9 +614,15 @@ void FrameMac::setStatusBarText(const String& status)
     String text = status;
     text.replace('\\', backslashAsCurrencySymbol());
     
+    // We want the temporaries allocated here to be released even before returning to the 
+    // event loop; see <http://bugzilla.opendarwin.org/show_bug.cgi?id=9880>.
+    NSAutoreleasePool* localPool = [[NSAutoreleasePool alloc] init];
+
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
     [_bridge setStatusText:text];
     END_BLOCK_OBJC_EXCEPTIONS;
+
+    [localPool release];
 }
 
 void FrameMac::scheduleClose()
@@ -628,17 +637,29 @@ void FrameMac::scheduleClose()
 void FrameMac::focusWindow()
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
     // If we're a top level window, bring the window to the front.
     if (!tree()->parent())
         [_bridge activateWindow];
-    NSView *view = d->m_view->getDocumentView();
-    if ([_bridge firstResponder] != view)
-        [_bridge makeFirstResponder:view];
+
+    // Might not have a view yet: this could be a child frame that has not yet received its first byte of data.
+    // FIXME: Should remember that the frame needs focus.  See <rdar://problem/4645685>.
+    if (d->m_view) {
+        NSView *view = d->m_view->getDocumentView();
+        if ([_bridge firstResponder] != view)
+            [_bridge makeFirstResponder:view];
+    }
+
     END_BLOCK_OBJC_EXCEPTIONS;
 }
 
 void FrameMac::unfocusWindow()
 {
+    // Might not have a view yet: this could be a child frame that has not yet received its first byte of data.
+    // FIXME: Should remember that the frame needs to unfocus.  See <rdar://problem/4645685>.
+    if (!d->m_view)
+        return;
+
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
     NSView *view = d->m_view->getDocumentView();
     if ([_bridge firstResponder] == view) {
@@ -664,17 +685,18 @@ String FrameMac::advanceToNextMisspelling(bool startBeforeSelection)
     
     // Start at the end of the selection, search to edge of document.  Starting at the selection end makes
     // repeated "check spelling" commands work.
+    Selection selection(selectionController()->selection());
     RefPtr<Range> searchRange(rangeOfContents(document()));
     bool startedWithSelection = false;
-    if (selection().start().node()) {
+    if (selection.start().node()) {
         startedWithSelection = true;
         if (startBeforeSelection) {
-            VisiblePosition start(selection().start(), selection().affinity());
+            VisiblePosition start(selection.visibleStart());
             // We match AppKit's rule: Start 1 character before the selection.
             VisiblePosition oneBeforeStart = start.previous();
             setStart(searchRange.get(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);
         } else
-            setStart(searchRange.get(), VisiblePosition(selection().end(), selection().affinity()));
+            setStart(searchRange.get(), selection.visibleEnd());
     }
 
     // If we're not in an editable node, try to find one, make that our range to work in
@@ -690,7 +712,7 @@ String FrameMac::advanceToNextMisspelling(bool startBeforeSelection)
     
     // topNode defines the whole range we want to operate on 
     Node *topNode = editableNode->rootEditableElement();
-    searchRange->setEndAfter(topNode, exception);
+    searchRange->setEnd(topNode, maxDeepOffset(topNode), exception);
 
     // Make sure start of searchRange is not in the middle of a word.  Jumping back a char and then
     // forward by a word happens to do the trick.
@@ -722,7 +744,7 @@ String FrameMac::advanceToNextMisspelling(bool startBeforeSelection)
         if (!it.atEnd()) {      // we may be starting at the end of the doc, and already by atEnd
             const UChar* chars = it.characters();
             int len = it.length();
-            if (len > 1 || !QChar(chars[0]).isSpace()) {
+            if (len > 1 || !DeprecatedChar(chars[0]).isSpace()) {
                 NSString *chunk = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(chars) length:len freeWhenDone:NO];
                 NSRange misspelling = [checker checkSpellingOfString:chunk startingAt:0 language:nil wrap:NO inSpellDocumentWithTag:[_bridge spellCheckerDocumentTag] wordCount:NULL];
                 [chunk release];
@@ -736,7 +758,7 @@ String FrameMac::advanceToNextMisspelling(bool startBeforeSelection)
                     DeprecatedString result = chars.string(misspelling.length);
                     misspellingRange->setEnd(chars.range()->startContainer(exception), chars.range()->startOffset(exception), exception);
 
-                    setSelection(SelectionController(misspellingRange.get(), DOWNSTREAM));
+                    selectionController()->setSelection(Selection(misspellingRange.get(), DOWNSTREAM));
                     revealSelection();
                     // Mark misspelling in document.
                     document()->addMarker(misspellingRange.get(), DocumentMarker::Spelling);
@@ -752,7 +774,7 @@ String FrameMac::advanceToNextMisspelling(bool startBeforeSelection)
             } else {
                 // we've gone from the selection to the end of doc, now wrap around
                 wrapped = YES;
-                searchRange->setStartBefore(topNode, exception);
+                searchRange->setStart(topNode, 0, exception);
                 // going until the end of the very first chunk we tested is far enough
                 searchRange->setEnd(searchEndAfterWrapNode, searchEndAfterWrapOffset, exception);
                 it = WordAwareIterator(searchRange.get());
@@ -769,13 +791,13 @@ bool FrameMac::wheelEvent(NSEvent *event)
 
     if (v) {
         NSEvent *oldCurrentEvent = _currentEvent;
-        _currentEvent = KWQRetain(event);
+        _currentEvent = HardRetain(event);
 
         PlatformWheelEvent qEvent(event);
         v->handleWheelEvent(qEvent);
 
         ASSERT(_currentEvent == event);
-        KWQRelease(event);
+        HardRelease(event);
         _currentEvent = oldCurrentEvent;
 
         if (qEvent.isAccepted())
@@ -785,21 +807,21 @@ bool FrameMac::wheelEvent(NSEvent *event)
     // FIXME: The scrolling done here should be done in the default handlers
     // of the elements rather than here in the part.
 
-    KWQScrollDirection direction;
+    ScrollDirection direction;
     float multiplier;
     float deltaX = [event deltaX];
     float deltaY = [event deltaY];
     if (deltaX < 0) {
-        direction = KWQScrollRight;
+        direction = ScrollRight;
         multiplier = -deltaX;
     } else if (deltaX > 0) {
-        direction = KWQScrollLeft;
+        direction = ScrollLeft;
         multiplier = deltaX;
     } else if (deltaY < 0) {
-        direction = KWQScrollDown;
+        direction = ScrollDown;
         multiplier = -deltaY;
     }  else if (deltaY > 0) {
-        direction = KWQScrollUp;
+        direction = ScrollUp;
         multiplier = deltaY;
     } else
         return false;
@@ -820,7 +842,7 @@ bool FrameMac::wheelEvent(NSEvent *event)
     if (!r)
         return false;
     
-    return r->scroll(direction, KWQScrollWheel, multiplier);
+    return r->scroll(direction, ScrollByWheel, multiplier);
 }
 
 void FrameMac::startRedirectionTimer()
@@ -871,23 +893,34 @@ String FrameMac::mimeTypeForFileName(const String& fileName) const
     return String();
 }
 
-NSView* FrameMac::nextKeyViewInFrame(Node* node, KWQSelectionDirection direction)
+NSView* FrameMac::nextKeyViewInFrame(Node* n, SelectionDirection direction, bool* focusCallResultedInViewBeingCreated)
 {
     Document* doc = document();
     if (!doc)
         return nil;
     
+    RefPtr<Node> node = n;
     for (;;) {
-        node = direction == KWQSelectingNext
-            ? doc->nextFocusNode(node) : doc->previousFocusNode(node);
+        node = direction == SelectingNext
+            ? doc->nextFocusNode(node.get()) : doc->previousFocusNode(node.get());
         if (!node)
             return nil;
         
         RenderObject* renderer = node->renderer();
+        
         if (!renderer->isWidget()) {
-            static_cast<Element*>(node)->focus(); 
-            [_bridge willMakeFirstResponderForNodeFocus];
-            return [_bridge documentView];
+            static_cast<Element*>(node.get())->focus(); 
+            // The call to focus might have triggered event handlers that causes the 
+            // current renderer to be destroyed.
+            if (!(renderer = node->renderer()))
+                continue;
+                
+            // FIXME: When all input elements are native, we should investigate if this extra check is needed
+            if (!renderer->isWidget()) {
+                [_bridge willMakeFirstResponderForNodeFocus];
+                return [_bridge documentView];
+            } else if (focusCallResultedInViewBeingCreated)
+                *focusCallResultedInViewBeingCreated = true;
         }
 
         if (Widget* widget = static_cast<RenderWidget*>(renderer)->widget()) {
@@ -902,22 +935,37 @@ NSView* FrameMac::nextKeyViewInFrame(Node* node, KWQSelectionDirection direction
     }
 }
 
-NSView *FrameMac::nextKeyViewInFrameHierarchy(Node *node, KWQSelectionDirection direction)
+NSView *FrameMac::nextKeyViewInFrameHierarchy(Node *node, SelectionDirection direction)
 {
-    NSView *next = nextKeyViewInFrame(node, direction);
+    bool focusCallResultedInViewBeingCreated = false;
+    NSView *next = nextKeyViewInFrame(node, direction, &focusCallResultedInViewBeingCreated);
     if (!next)
         if (FrameMac *parent = Mac(tree()->parent()))
             next = parent->nextKeyViewInFrameHierarchy(ownerElement(), direction);
     
     // remove focus from currently focused node if we're giving focus to another view
-    if (next && (next != [_bridge documentView]))
+    // unless the other view was created as a result of calling focus in nextKeyViewWithFrame.
+    // FIXME: The focusCallResultedInViewBeingCreated calls can be removed when all input element types
+    // have been made native.
+    if (next && (next != [_bridge documentView] && !focusCallResultedInViewBeingCreated))
         if (Document *doc = document())
             doc->setFocusNode(0);
+
+    // The common case where a view was created is when an <input> element changed from native 
+    // to non-native. When this happens, HTMLGenericFormElement::attach() method will call setFocus()
+    // on the widget. For views with a field editor, setFocus() will set the active responder to be the field editor. 
+    // In this case, we want to return the field editor as the next key view. Otherwise, the focus will be lost
+    // and a blur message will be sent. 
+    // FIXME: This code can be removed when all input element types are native.
+    if (focusCallResultedInViewBeingCreated) {
+        if ([[next window] firstResponder] == [[next window] fieldEditor:NO forObject:next])
+            return [[next window] fieldEditor:NO forObject:next];
+    }
     
     return next;
 }
 
-NSView *FrameMac::nextKeyView(Node *node, KWQSelectionDirection direction)
+NSView *FrameMac::nextKeyView(Node *node, SelectionDirection direction)
 {
     NSView * next;
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
@@ -928,7 +976,7 @@ NSView *FrameMac::nextKeyView(Node *node, KWQSelectionDirection direction)
 
     // Look at views from the top level part up, looking for a next key view that we can use.
 
-    next = direction == KWQSelectingNext
+    next = direction == SelectingNext
         ? [_bridge nextKeyViewOutsideWebFrameViews]
         : [_bridge previousKeyViewOutsideWebFrameViews];
 
@@ -941,7 +989,7 @@ NSView *FrameMac::nextKeyView(Node *node, KWQSelectionDirection direction)
     return nextKeyViewInFrameHierarchy(0, direction);
 }
 
-NSView *FrameMac::nextKeyViewForWidget(Widget *startingWidget, KWQSelectionDirection direction)
+NSView *FrameMac::nextKeyViewForWidget(Widget *startingWidget, SelectionDirection direction)
 {
     // Use the event filter object to figure out which RenderWidget owns this Widget and get to the DOM.
     // Then get the next key view in the order determined by the DOM.
@@ -1041,6 +1089,9 @@ bool FrameMac::tabsToAllControls() const
 
 KJS::Bindings::RootObject *FrameMac::executionContextForDOM()
 {
+    if (!jScriptEnabled())
+        return 0;
+
     return bindingRootObject();
 }
 
@@ -1066,7 +1117,7 @@ WebScriptObject *FrameMac::windowScriptObject()
     if (!_windowScriptObject) {
         KJS::JSLock lock;
         KJS::JSObject *win = KJS::Window::retrieveWindow(this);
-        _windowScriptObject = KWQRetainNSRelease([[WebScriptObject alloc] _initWithJSObject:win originExecutionContext:bindingRootObject() executionContext:bindingRootObject()]);
+        _windowScriptObject = HardRetainWithNSRelease([[WebScriptObject alloc] _initWithJSObject:win originExecutionContext:bindingRootObject() executionContext:bindingRootObject()]);
     }
 
     return _windowScriptObject;
@@ -1097,10 +1148,10 @@ void FrameMac::partClearedInBegin()
         [_bridge windowObjectCleared];
 }
 
-void FrameMac::openURLFromPageCache(KWQPageState *state)
+void FrameMac::openURLFromPageCache(WebCorePageState *state)
 {
-    // It's safe to assume none of the KWQPageState methods will raise
-    // exceptions, since KWQPageState is implemented by WebCore and
+    // It's safe to assume none of the WebCorePageState methods will raise
+    // exceptions, since WebCorePageState is implemented by WebCore and
     // does not throw
 
     Document *doc = [state document];
@@ -1346,7 +1397,7 @@ bool FrameMac::keyEvent(NSEvent *event)
     }
 
     NSEvent *oldCurrentEvent = _currentEvent;
-    _currentEvent = KWQRetain(event);
+    _currentEvent = HardRetain(event);
 
     PlatformKeyboardEvent qEvent(event);
     result = !EventTargetNodeCast(node)->dispatchKeyEvent(qEvent);
@@ -1362,7 +1413,7 @@ bool FrameMac::keyEvent(NSEvent *event)
     }
 
     ASSERT(_currentEvent == event);
-    KWQRelease(event);
+    HardRelease(event);
     _currentEvent = oldCurrentEvent;
 
     return result;
@@ -1426,7 +1477,11 @@ bool FrameMac::passMouseDownEventToWidget(Widget* widget)
         // In the case where we just became first responder, we should send the mouseDown:
         // to the NSTextField, not the NSTextField's editor. This code makes sure that happens.
         // If we don't do this, we see a flash of selected text when clicking in a text field.
-        if (![_bridge wasFirstResponderAtMouseDownTime:view] && [view isKindOfClass:[NSTextView class]]) {
+        // FIXME: This is the only caller of textViewWasFirstResponderAtMouseDownTime. When we
+        // eliminate all use of NSTextField/NSTextView in form fields we can eliminate this code,
+        // and textViewWasFirstResponderAtMouseDownTime:, and the instance variable WebHTMLView
+        // keeps solely to support textViewWasFirstResponderAtMouseDownTime:.
+        if ([view isKindOfClass:[NSTextView class]] && ![_bridge textViewWasFirstResponderAtMouseDownTime:(NSTextView *)view]) {
             NSView *superview = view;
             while (superview != nodeView) {
                 superview = [superview superview];
@@ -1671,7 +1726,7 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
                         _dragClipboard->setDragImageElement(_dragSrc.get(), IntPoint() + delta);
                     } 
 
-                    _mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDown);
+                    _mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDown) && mayCopy();
                     // Invalidate clipboard here against anymore pasteboard writing for security.  The drag
                     // image can still be changed as we drag, but not the pasteboard data.
                     _dragClipboard->setAccessPolicy(ClipboardMac::ImageWritable);
@@ -1698,7 +1753,7 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
                     BOOL startedDrag = [_bridge startDraggingImage:dragImage at:dragLoc operation:srcOp event:_currentEvent sourceIsDHTML:_dragSrcIsDHTML DHTMLWroteData:wcWrotePasteboard];
                     if (!startedDrag && _dragSrcMayBeDHTML) {
                         // WebKit canned the drag at the last minute - we owe _dragSrc a DRAGEND event
-                        PlatformMouseEvent event;
+                        PlatformMouseEvent event(PlatformMouseEvent::currentEvent);
                         dispatchDragSrcEvent(dragendEvent, event);
                         _mouseDownMayStartDrag = false;
                     }
@@ -1756,12 +1811,14 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
 // the event handler NOT setting the return value to false
 bool FrameMac::dispatchCPPEvent(const AtomicString &eventType, ClipboardMac::AccessPolicy policy)
 {
-    Node* target = d->m_selection.start().element();
+    Node* target = selectionController()->start().element();
     if (!target && document())
         target = document()->body();
     if (!target)
         return true;
-
+    if (target->isShadowNode())
+        target = target->shadowParentNode();
+    
     RefPtr<ClipboardMac> clipboard = new ClipboardMac(false, [NSPasteboard generalPasteboard], (ClipboardMac::AccessPolicy)policy);
 
     ExceptionCode ec = 0;
@@ -1780,23 +1837,26 @@ bool FrameMac::dispatchCPPEvent(const AtomicString &eventType, ClipboardMac::Acc
 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
 // normally selectable to implement copy/paste (like divs, or a document body).
 
-bool FrameMac::mayCut()
+bool FrameMac::mayDHTMLCut()
 {
-    return !dispatchCPPEvent(beforecutEvent, ClipboardMac::Numb);
+    return mayCopy() && !dispatchCPPEvent(beforecutEvent, ClipboardMac::Numb);
 }
 
-bool FrameMac::mayCopy()
+bool FrameMac::mayDHTMLCopy()
 {
-    return !dispatchCPPEvent(beforecopyEvent, ClipboardMac::Numb);
+    return mayCopy() && !dispatchCPPEvent(beforecopyEvent, ClipboardMac::Numb);
 }
 
-bool FrameMac::mayPaste()
+bool FrameMac::mayDHTMLPaste()
 {
     return !dispatchCPPEvent(beforepasteEvent, ClipboardMac::Numb);
 }
 
-bool FrameMac::tryCut()
+bool FrameMac::tryDHTMLCut()
 {
+    if (!mayCopy())
+        return false;
+
     // Must be done before oncut adds types and data to the pboard,
     // also done for security, as it erases data from the last copy/paste.
     [[NSPasteboard generalPasteboard] declareTypes:[NSArray array] owner:nil];
@@ -1804,8 +1864,11 @@ bool FrameMac::tryCut()
     return !dispatchCPPEvent(cutEvent, ClipboardMac::Writable);
 }
 
-bool FrameMac::tryCopy()
+bool FrameMac::tryDHTMLCopy()
 {
+    if (!mayCopy())
+        return false;
+
     // Must be done before oncopy adds types and data to the pboard,
     // also done for security, as it erases data from the last copy/paste.
     [[NSPasteboard generalPasteboard] declareTypes:[NSArray array] owner:nil];
@@ -1813,7 +1876,7 @@ bool FrameMac::tryCopy()
     return !dispatchCPPEvent(copyEvent, ClipboardMac::Writable);
 }
 
-bool FrameMac::tryPaste()
+bool FrameMac::tryDHTMLPaste()
 {
     return !dispatchCPPEvent(pasteEvent, ClipboardMac::Readable);
 }
@@ -1949,7 +2012,7 @@ void FrameMac::mouseDown(NSEvent *event)
     _dragSrc = 0;
     
     NSEvent *oldCurrentEvent = _currentEvent;
-    _currentEvent = KWQRetain(event);
+    _currentEvent = HardRetain(event);
     m_mouseDown = PlatformMouseEvent(event);
     NSPoint loc = [event locationInWindow];
     m_mouseDownPos = d->m_view->viewportToContents(IntPoint(loc));
@@ -1961,7 +2024,7 @@ void FrameMac::mouseDown(NSEvent *event)
     v->handleMousePressEvent(event);
     
     ASSERT(_currentEvent == event);
-    KWQRelease(event);
+    HardRelease(event);
     _currentEvent = oldCurrentEvent;
 
     END_BLOCK_OBJC_EXCEPTIONS;
@@ -1977,12 +2040,12 @@ void FrameMac::mouseDragged(NSEvent *event)
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
     NSEvent *oldCurrentEvent = _currentEvent;
-    _currentEvent = KWQRetain(event);
+    _currentEvent = HardRetain(event);
 
     v->handleMouseMoveEvent(event);
     
     ASSERT(_currentEvent == event);
-    KWQRelease(event);
+    HardRelease(event);
     _currentEvent = oldCurrentEvent;
 
     END_BLOCK_OBJC_EXCEPTIONS;
@@ -1997,7 +2060,7 @@ void FrameMac::mouseUp(NSEvent *event)
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
     NSEvent *oldCurrentEvent = _currentEvent;
-    _currentEvent = KWQRetain(event);
+    _currentEvent = HardRetain(event);
 
     // Our behavior here is a little different that Qt. Qt always sends
     // a mouse release event, even for a double click. To correct problems
@@ -2013,7 +2076,7 @@ void FrameMac::mouseUp(NSEvent *event)
         v->handleMouseReleaseEvent(event);
     
     ASSERT(_currentEvent == event);
-    KWQRelease(event);
+    HardRelease(event);
     _currentEvent = oldCurrentEvent;
     
     _mouseDownView = nil;
@@ -2093,12 +2156,12 @@ void FrameMac::mouseMoved(NSEvent *event)
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
     NSEvent *oldCurrentEvent = _currentEvent;
-    _currentEvent = KWQRetain(event);
+    _currentEvent = HardRetain(event);
     
     v->handleMouseMoveEvent(event);
     
     ASSERT(_currentEvent == event);
-    KWQRelease(event);
+    HardRelease(event);
     _currentEvent = oldCurrentEvent;
 
     END_BLOCK_OBJC_EXCEPTIONS;
@@ -2129,7 +2192,7 @@ bool FrameMac::sendContextMenuEvent(NSEvent *event)
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
 
     NSEvent *oldCurrentEvent = _currentEvent;
-    _currentEvent = KWQRetain(event);
+    _currentEvent = HardRetain(event);
     
     PlatformMouseEvent mouseEvent(event);
 
@@ -2145,7 +2208,7 @@ bool FrameMac::sendContextMenuEvent(NSEvent *event)
     }
 
     ASSERT(_currentEvent == event);
-    KWQRelease(event);
+    HardRelease(event);
     _currentEvent = oldCurrentEvent;
 
     return swallowEvent;
@@ -2384,13 +2447,13 @@ NSAttributedString *FrameMac::attributedString(Node *_start, int startOffset, No
                         maxMarkerWidth = MAX([font pointSize], maxMarkerWidth);
                         switch(style->listStyleType()) {
                             case DISC:
-                                listText += ((QChar)BULLET_CHAR);
+                                listText += ((DeprecatedChar)BULLET_CHAR);
                                 break;
                             case CIRCLE:
-                                listText += ((QChar)CIRCLE_CHAR);
+                                listText += ((DeprecatedChar)CIRCLE_CHAR);
                                 break;
                             case SQUARE:
-                                listText += ((QChar)SQUARE_CHAR);
+                                listText += ((DeprecatedChar)SQUARE_CHAR);
                                 break;
                             case LNONE:
                                 break;
@@ -2643,6 +2706,13 @@ NSImage *FrameMac::imageFromRect(NSRect rect) const
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
     
     NSRect bounds = [view bounds];
+    
+    // Round image rect size in window coordinate space to avoid pixel cracks at HiDPI (4622794)
+    rect = [view convertRect:rect toView:nil];
+    rect.size.height = roundf(rect.size.height);
+    rect.size.width = roundf(rect.size.width);
+    rect = [view convertRect:rect fromView:nil];
+    
     resultImage = [[[NSImage alloc] initWithSize:rect.size] autorelease];
 
     if (rect.size.width != 0 && rect.size.height != 0) {
@@ -2667,11 +2737,11 @@ NSImage *FrameMac::imageFromRect(NSRect rect) const
     return nil;
 }
 
-NSImage *FrameMac::selectionImage() const
+NSImage* FrameMac::selectionImage(bool forceWhiteText) const
 {
-    d->m_drawSelectionOnly = true;  // invoke special drawing mode
+    d->m_paintRestriction = forceWhiteText ? PaintRestrictionSelectionOnlyWhiteText : PaintRestrictionSelectionOnly;
     NSImage *result = imageFromRect(visibleSelectionRect());
-    d->m_drawSelectionOnly = false;
+    d->m_paintRestriction = PaintRestrictionNone;
     return result;
 }
 
@@ -2705,7 +2775,7 @@ NSFont *FrameMac::fontForSelection(bool *hasMultipleFonts) const
     if (hasMultipleFonts)
         *hasMultipleFonts = false;
 
-    if (!d->m_selection.isRange()) {
+    if (!selectionController()->isRange()) {
         Node *nodeToRemove;
         RenderStyle *style = styleForSelectionStart(nodeToRemove); // sets nodeToRemove
 
@@ -2724,7 +2794,7 @@ NSFont *FrameMac::fontForSelection(bool *hasMultipleFonts) const
 
     NSFont *font = nil;
 
-    RefPtr<Range> range = d->m_selection.toRange();
+    RefPtr<Range> range = selectionController()->toRange();
     Node *startNode = range->editingStartPosition().node();
     if (startNode != nil) {
         Node *pastEnd = range->pastEndNode();
@@ -2818,7 +2888,7 @@ NSWritingDirection FrameMac::baseWritingDirectionForSelectionStart() const
 {
     NSWritingDirection result = NSWritingDirectionLeftToRight;
 
-    Position pos = VisiblePosition(d->m_selection.start(), d->m_selection.affinity()).deepEquivalent();
+    Position pos = selectionController()->selection().visibleStart().deepEquivalent();
     Node *node = pos.node();
     if (!node || !node->renderer() || !node->renderer()->containingBlock())
         return result;
@@ -2850,8 +2920,8 @@ void FrameMac::setBridge(WebCoreFrameBridge *bridge)
     if (_bridge == bridge)
         return;
 
-    KWQRetain(bridge);
-    KWQRelease(_bridge);
+    HardRetain(bridge);
+    HardRelease(_bridge);
     _bridge = bridge;
 }
 
@@ -2937,11 +3007,16 @@ static KJS::Bindings::Instance *getInstanceForView(NSView *aView)
             return KJS::Bindings::Instance::createBindingForLanguageInstance (KJS::Bindings::Instance::ObjectiveCLanguage, object, executionContext);
         }
     }
-    else if ([aView respondsToSelector:@selector(pluginScriptableObject)]){
-        void *object = [aView pluginScriptableObject];
+    else if ([aView respondsToSelector:@selector(createPluginScriptableObject)]) {
+        NPObject *object = [aView createPluginScriptableObject];
         if (object) {
-            KJS::Bindings::RootObject *executionContext = KJS::Bindings::RootObject::findRootObjectForNativeHandleFunction ()(aView);
-            return KJS::Bindings::Instance::createBindingForLanguageInstance (KJS::Bindings::Instance::CLanguage, object, executionContext);
+            KJS::Bindings::RootObject *executionContext = KJS::Bindings::RootObject::findRootObjectForNativeHandleFunction()(aView);
+            KJS::Bindings::Instance *instance = KJS::Bindings::Instance::createBindingForLanguageInstance(KJS::Bindings::Instance::CLanguage, object, executionContext);
+            
+            // -createPluginScriptableObject returns a retained NPObject.  The caller is expected to release it.
+            _NPN_ReleaseObject(object);
+            
+            return instance;
         }
     }
     return 0;
@@ -2972,32 +3047,45 @@ void FrameMac::cleanupPluginRootObjects()
     m_rootObjects.clear();
 }
 
-void FrameMac::registerCommandForUndoOrRedo(const EditCommandPtr &cmd, bool isRedo)
+void FrameMac::registerCommandForUndoOrRedo(PassRefPtr<EditCommand> cmd, bool isRedo)
 {
-    ASSERT(cmd.get());
-    KWQEditCommand *kwq = [KWQEditCommand commandWithEditCommand:cmd.get()];
-    NSUndoManager *undoManager = [_bridge undoManager];
-    [undoManager registerUndoWithTarget:_bridge selector:(isRedo ? @selector(redoEditing:) : @selector(undoEditing:)) object:kwq];
-    NSString *actionName = [_bridge nameForUndoAction:static_cast<WebUndoAction>(cmd.editingAction())];
+    ASSERT(cmd);
+    WebUndoAction action = static_cast<WebUndoAction>(cmd->editingAction());
+    NSUndoManager* undoManager = [_bridge undoManager];
+    WebCoreEditCommand* command = [WebCoreEditCommand commandWithEditCommand:cmd];
+    NSString* actionName = [_bridge nameForUndoAction:action];
+    [undoManager registerUndoWithTarget:_bridge selector:(isRedo ? @selector(redoEditing:) : @selector(undoEditing:)) object:command];
     if (actionName)
         [undoManager setActionName:actionName];
     _haveUndoRedoOperations = YES;
 }
 
-void FrameMac::registerCommandForUndo(const EditCommandPtr &cmd)
+void FrameMac::registerCommandForUndo(PassRefPtr<EditCommand> cmd)
 {
-    registerCommandForUndoOrRedo(cmd, NO);
+    registerCommandForUndoOrRedo(cmd, false);
 }
 
-void FrameMac::registerCommandForRedo(const EditCommandPtr &cmd)
+void FrameMac::registerCommandForRedo(PassRefPtr<EditCommand> cmd)
 {
-    registerCommandForUndoOrRedo(cmd, YES);
+    registerCommandForUndoOrRedo(cmd, true);
 }
 
 void FrameMac::clearUndoRedoOperations()
 {
     if (_haveUndoRedoOperations) {
-        [[_bridge undoManager] removeAllActionsWithTarget:_bridge];
+        // workaround for <rdar://problem/4645507> NSUndoManager dies
+        // with uncaught exception when undo items cleared while
+        // groups are open
+        NSUndoManager *undoManager = [_bridge undoManager];
+        int groupingLevel = [undoManager groupingLevel];
+        for (int i = 0; i < groupingLevel; ++i)
+            [undoManager endUndoGrouping];
+        
+        [undoManager removeAllActionsWithTarget:_bridge];
+
+        for (int i = 0; i < groupingLevel; ++i)
+            [undoManager beginUndoGrouping];
+
         _haveUndoRedoOperations = NO;
     }
 }
@@ -3058,10 +3146,10 @@ void FrameMac::markMisspellingsInAdjacentWords(const VisiblePosition &p)
 {
     if (![_bridge isContinuousSpellCheckingEnabled])
         return;
-    markMisspellings(SelectionController(startOfWord(p, LeftWordIfOnBoundary), endOfWord(p, RightWordIfOnBoundary)));
+    markMisspellings(Selection(startOfWord(p, LeftWordIfOnBoundary), endOfWord(p, RightWordIfOnBoundary)));
 }
 
-void FrameMac::markMisspellings(const SelectionController &selection)
+void FrameMac::markMisspellings(const Selectionselection)
 {
     // This function is called with a selection already expanded to word boundaries.
     // Might be nice to assert that here.
@@ -3089,7 +3177,7 @@ void FrameMac::markMisspellings(const SelectionController &selection)
     while (!it.atEnd()) {      // we may be starting at the end of the doc, and already by atEnd
         const UChar* chars = it.characters();
         int len = it.length();
-        if (len > 1 || !QChar(chars[0]).isSpace()) {
+        if (len > 1 || !DeprecatedChar(chars[0]).isSpace()) {
             NSString *chunk = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(chars) length:len freeWhenDone:NO];
             int startIndex = 0;
             // Loop over the chunk to find each misspelling in it.
@@ -3118,38 +3206,29 @@ void FrameMac::markMisspellings(const SelectionController &selection)
     }
 }
 
-void FrameMac::respondToChangedSelection(const SelectionController &oldSelection, bool closeTyping)
+void FrameMac::respondToChangedSelection(const Selection &oldSelection, bool closeTyping)
 {
     if (document()) {
         if ([_bridge isContinuousSpellCheckingEnabled]) {
-            SelectionController oldAdjacentWords = SelectionController();
+            Selection oldAdjacentWords;
             
             // If this is a change in selection resulting from a delete operation, oldSelection may no longer
             // be in the document.
             if (oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
-                VisiblePosition oldStart(oldSelection.start(), oldSelection.affinity());
-                oldAdjacentWords = SelectionController(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));   
+                VisiblePosition oldStart(oldSelection.visibleStart());
+                oldAdjacentWords = Selection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));   
             }
 
-            VisiblePosition newStart(selection().start(), selection().affinity());
-            SelectionController newAdjacentWords(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
-
-            if (oldAdjacentWords != newAdjacentWords) {
-                // Mark misspellings in the portion that was previously unmarked because of
-                // the proximity of the start of the selection. We only spell check words in
-                // the vicinity of the start of the old selection because the spelling checker
-                // is not fast enough to do a lot of spelling checking implicitly. This matches
-                // AppKit. This function is really the only code that knows that rule. The
-                // markMisspellings function is prepared to handler larger ranges.
+            VisiblePosition newStart(selectionController()->selection().visibleStart());
+            Selection newAdjacentWords(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
 
-                // When typing we check spelling elsewhere, so don't redo it here.
-                if (closeTyping)
-                    markMisspellings(oldAdjacentWords);
+            // When typing we check spelling elsewhere, so don't redo it here.
+            if (closeTyping && oldAdjacentWords != newAdjacentWords)
+                markMisspellings(oldAdjacentWords);
 
-                // This only erases a marker in the first word of the selection.
-                // Perhaps peculiar, but it matches AppKit.
-                document()->removeMarkers(newAdjacentWords.toRange().get(), DocumentMarker::Spelling);
-            }
+            // This only erases a marker in the first word of the selection.
+            // Perhaps peculiar, but it matches AppKit.
+            document()->removeMarkers(newAdjacentWords.toRange().get(), DocumentMarker::Spelling);
         } else
             // When continuous spell checking is off, no markers appear after the selection changes.
             document()->removeMarkers(DocumentMarker::Spelling);
@@ -3158,7 +3237,7 @@ void FrameMac::respondToChangedSelection(const SelectionController &oldSelection
     [_bridge respondToChangedSelection];
 }
 
-bool FrameMac::shouldChangeSelection(const SelectionController &oldSelection, const SelectionController &newSelection, EAffinity affinity, bool stillSelecting) const
+bool FrameMac::shouldChangeSelection(const Selection& oldSelection, const Selection& newSelection, EAffinity affinity, bool stillSelecting) const
 {
     return [_bridge shouldChangeSelectedDOMRange:[DOMRange _rangeWith:oldSelection.toRange().get()]
                                       toDOMRange:[DOMRange _rangeWith:newSelection.toRange().get()]
@@ -3166,10 +3245,18 @@ bool FrameMac::shouldChangeSelection(const SelectionController &oldSelection, co
                                   stillSelecting:stillSelecting];
 }
 
-void FrameMac::respondToChangedContents()
+bool FrameMac::shouldDeleteSelection(const Selection& selection) const
+{
+    return [_bridge shouldDeleteSelectedDOMRange:[DOMRange _rangeWith:selection.toRange().get()]];
+}
+
+void FrameMac::respondToChangedContents(const Selection& selection)
 {
-    if (AccessibilityObjectCache::accessibilityEnabled())
-        renderer()->document()->getAccObjectCache()->postNotificationToTopWebArea(renderer(), "AXValueChanged");
+    if (AXObjectCache::accessibilityEnabled()) {
+        Node* node = selection.start().node();
+        if (node)
+            renderer()->document()->axObjectCache()->postNotification(node->renderer(), "AXValueChanged");
+    }
     [_bridge respondToChangedContents];
 }
 
@@ -3230,6 +3317,11 @@ void FrameMac::textDidChangeInTextArea(Element* textarea)
 
 bool FrameMac::doTextFieldCommandFromEvent(Element* input, const PlatformKeyboardEvent* event)
 {
+    // FIXME: We might eventually need to make sure key bindings for editing work even with
+    // events created with the DOM API. Those don't have a PlatformKeyboardEvent.
+    if (!event)
+        return false;
+
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
     return [_bridge textField:(DOMHTMLInputElement *)[DOMElement _elementWith:input] doCommandBySelector:selectorForKeyEvent(event)];
     END_BLOCK_OBJC_EXCEPTIONS;
@@ -3244,6 +3336,31 @@ void FrameMac::textWillBeDeletedInTextField(Element* input)
     END_BLOCK_OBJC_EXCEPTIONS;
 }
 
+bool FrameMac::inputManagerHasMarkedText() const
+{
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+    return [[NSInputManager currentInputManager] hasMarkedText];
+    END_BLOCK_OBJC_EXCEPTIONS
+    return false;
+}
+
+const short enableRomanKeyboardsOnly = -23;
+void FrameMac::setSecureKeyboardEntry(bool enable)
+{
+    if (enable) {
+        EnableSecureEventInput();
+        KeyScript(enableRomanKeyboardsOnly);
+    } else {
+        DisableSecureEventInput();
+        KeyScript(smKeyEnableKybds);
+    }
+}
+
+bool FrameMac::isSecureKeyboardEntry()
+{
+    return IsSecureEventInputEnabled();
+}
+
 static DeprecatedValueList<MarkedTextUnderline> convertAttributesToUnderlines(const Range *markedTextRange, NSArray *attributes, NSArray *ranges)
 {
     DeprecatedValueList<MarkedTextUnderline> result;
@@ -3357,7 +3474,7 @@ void FrameMac::dashboardRegionsChanged()
     [_bridge dashboardRegionsChanged:webRegions];
 }
 
-bool FrameMac::isCharacterSmartReplaceExempt(const QChar &c, bool isPreviousChar)
+bool FrameMac::isCharacterSmartReplaceExempt(const DeprecatedChar &c, bool isPreviousChar)
 {
     return [_bridge isCharacterSmartReplaceExempt:c.unicode() isPreviousCharacter:isPreviousChar];
 }