LayoutTests:
authorggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 Oct 2006 23:56:37 +0000 (23:56 +0000)
committerggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 31 Oct 2006 23:56:37 +0000 (23:56 +0000)
        Added layout test for copying password field.

        * editing/pasteboard/copy-in-password-field-expected.txt: Added.
        * editing/pasteboard/copy-in-password-field.html: Added.

WebCore:

        Reviewed by Alice.

        Moved some Editing code from WebKit, the bridge, and WebCore::Frame down
        to WebCore::Editor.

        Layout tests pass.

        Renamed "may*" to "can*" because "can" is more accurate (these functions
        aren't just about permission) and it matches WebKit.

        (WebCore::FrameMac::handleMouseMoveEvent): Directly test for dragging in a
        password field. Now that WebCore fully implements canCopy(), it doesn't just
        mean "the selection is not in a password field" anymore.
        (-[WebCoreFrameBridge _shouldAllowAccessFrom:]): Removed this #ifed-out code.
        The fact that it's not called anymore may represent a security issue, but I
        don't see how commented-out code will help reveal the issue, and the
        bridge is going away, anyway.
        * editing/SelectionController.h: Changed selection() calls to references
        to m_sel, to match the rest of the file.

WebKit:

        Reviewed by Alice.

        Moved some Editing code from WebKit, the bridge, and WebCore::Frame down
        to WebCore::Editor.

        * WebCoreSupport/WebFrameBridge.mm:
        * WebView/WebHTMLView.m:
        (-[WebHTMLView _shouldDeleteRange:]):
        (-[WebHTMLView _canCopy]):
        (-[WebHTMLView _canCut]):
        (-[WebHTMLView _canDelete]):
        (-[WebHTMLView _canPaste]):
        (-[WebHTMLView _canEdit]):
        (-[WebHTMLView _canEditRichly]):
        (-[WebHTMLView _isEditable]):
        (-[WebHTMLView _isSelectionInPasswordField]):
        (-[NSArray validateUserInterfaceItem:]):
        (-[NSArray _expandSelectionToGranularity:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@17504 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/pasteboard/copy-in-password-field-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/copy-in-password-field.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/WebCore.exp
WebCore/bridge/EditorClient.h
WebCore/bridge/mac/FrameMac.h
WebCore/bridge/mac/FrameMac.mm
WebCore/bridge/mac/WebCoreFrameBridge.h
WebCore/bridge/mac/WebCoreFrameBridge.mm
WebCore/editing/CommandByName.cpp
WebCore/editing/Editor.cpp
WebCore/editing/Editor.h
WebCore/editing/JSEditor.cpp
WebCore/editing/SelectionController.cpp
WebCore/editing/SelectionController.h
WebCore/page/Frame.cpp
WebCore/page/Frame.h
WebCore/page/FrameView.cpp
WebKit/ChangeLog
WebKit/WebCoreSupport/WebFrameBridge.mm
WebKit/WebView/WebHTMLView.m

index 436e32d16c1075f67a4dd7404a517b74f958efb9..3c42c7805791c3f95f872abf88c6954bf6043cc2 100644 (file)
@@ -1,3 +1,10 @@
+2006-10-31  Geoffrey Garen  <ggaren@apple.com>
+
+        Added layout test for copying password field.
+
+        * editing/pasteboard/copy-in-password-field-expected.txt: Added.
+        * editing/pasteboard/copy-in-password-field.html: Added.
+
 2006-10-31  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by harrison
diff --git a/LayoutTests/editing/pasteboard/copy-in-password-field-expected.txt b/LayoutTests/editing/pasteboard/copy-in-password-field-expected.txt
new file mode 100644 (file)
index 0000000..6dec088
--- /dev/null
@@ -0,0 +1,18 @@
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertText:[not modified] replacingDOMRange:range from 0 of #text > DIV to 14 of #text > DIV givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 14 of #text > DIV to 14 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+This test verifies that copying is disabled for password fields by attempting to copy from a password field and paste into a textfield. If the test passes, you'll see a of 'PASS' message below, and the textfield will remain unmodified.
+
+(The test is only meaningful in debug builds, since paste is disabled in release builds.)
+
+PASS document.getElementById("text").value is "[not modified]"
+
+
diff --git a/LayoutTests/editing/pasteboard/copy-in-password-field.html b/LayoutTests/editing/pasteboard/copy-in-password-field.html
new file mode 100644 (file)
index 0000000..84b58b4
--- /dev/null
@@ -0,0 +1,27 @@
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+
+<p>This test verifies that copying is disabled for password fields by attempting to
+copy from a password field and paste into a textfield. If the test
+passes, you'll see a of 'PASS' message below, and the textfield will remain unmodified.</p>
+<p>(The test is only meaningful in debug builds, since paste is disabled in release builds.)</p>
+<input type="password" id="password" value="Password Input">
+<input type="text" id="text" value="[not modified]">
+<hr>
+<p id="console"></p>
+
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script>
+// Overwrite the old pasteboard with default results
+document.getElementById("text").focus();
+document.execCommand("Copy");
+
+// Try to copy a password
+document.getElementById("password").focus();
+document.execCommand("Copy");
+
+// Paste
+document.getElementById("text").focus();
+document.execCommand("Paste");
+
+shouldBe('document.getElementById("text").value', '"[not modified]"');
+</script>
index d4964bb1be9e39aa291f748729fb9b9605d3e95f..840177d06d7e1a502f43e186aa7a8fc4031ab6fa 100644 (file)
@@ -1,3 +1,25 @@
+2006-10-31  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Alice.
+
+        Moved some Editing code from WebKit, the bridge, and WebCore::Frame down 
+        to WebCore::Editor.
+        
+        Layout tests pass.
+        
+        Renamed "may*" to "can*" because "can" is more accurate (these functions
+        aren't just about permission) and it matches WebKit.
+
+        (WebCore::FrameMac::handleMouseMoveEvent): Directly test for dragging in a 
+        password field. Now that WebCore fully implements canCopy(), it doesn't just
+        mean "the selection is not in a password field" anymore.
+        (-[WebCoreFrameBridge _shouldAllowAccessFrom:]): Removed this #ifed-out code. 
+        The fact that it's not called anymore may represent a security issue, but I
+        don't see how commented-out code will help reveal the issue, and the
+        bridge is going away, anyway.
+        * editing/SelectionController.h: Changed selection() calls to references
+        to m_sel, to match the rest of the file.
+
 2006-10-31  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by harrison
index 36022898a252badc23510bd57c0c19d12d02adb1..1ad40f37e00c59a21e48a88ea7a3d62602aa2eaf 100644 (file)
@@ -198,7 +198,6 @@ __ZN7WebCore5Frame11clearTimersEv
 __ZN7WebCore5Frame11completeURLERKNS_16DeprecatedStringE
 __ZN7WebCore5Frame11setSettingsEPNS_8SettingsE
 __ZN7WebCore5Frame12canCachePageEv
-__ZN7WebCore5Frame12hasSelectionEv
 __ZN7WebCore5Frame12ownerElementEv
 __ZN7WebCore5Frame13pauseTimeoutsEv
 __ZN7WebCore5Frame14scrollToAnchorERKNS_4KURLE
@@ -209,7 +208,6 @@ __ZN7WebCore5Frame20setSelectionFromNoneEv
 __ZN7WebCore5Frame21setProhibitsScrollingEb
 __ZN7WebCore5Frame22saveLocationPropertiesEPN3KJS15SavedPropertiesE
 __ZN7WebCore5Frame23saveInterpreterBuiltinsERN3KJS13SavedBuiltinsE
-__ZN7WebCore5Frame26isSelectionInPasswordFieldEv
 __ZN7WebCore5Frame6indentEv
 __ZN7WebCore5Frame7outdentEv
 __ZN7WebCore5Image21getTIFFRepresentationEv
@@ -227,13 +225,13 @@ __ZN7WebCore8Document13removeMarkersENS_14DocumentMarker10MarkerTypeE
 __ZN7WebCore8Document4bodyEv
 __ZN7WebCore8FrameMac10mouseMovedEP7NSEvent
 __ZN7WebCore8FrameMac10wheelEventEP7NSEvent
-__ZN7WebCore8FrameMac11mayDHTMLCutEv
+__ZN7WebCore8FrameMac11canDHTMLCutEv
 __ZN7WebCore8FrameMac11shouldCloseEv
 __ZN7WebCore8FrameMac11tryDHTMLCutEv
-__ZN7WebCore8FrameMac12mayDHTMLCopyEv
+__ZN7WebCore8FrameMac12canDHTMLCopyEv
 __ZN7WebCore8FrameMac12mouseDraggedEP7NSEvent
 __ZN7WebCore8FrameMac12tryDHTMLCopyEv
-__ZN7WebCore8FrameMac13mayDHTMLPasteEv
+__ZN7WebCore8FrameMac13canDHTMLPasteEv
 __ZN7WebCore8FrameMac13tryDHTMLPasteEv
 __ZN7WebCore8FrameMac18windowScriptObjectEv
 __ZN7WebCore8FrameMac20sendContextMenuEventEP7NSEvent
@@ -317,6 +315,7 @@ __ZNK7WebCore14ResourceLoader11frameLoaderEv
 __ZNK7WebCore16DeprecatedString11getNSStringEv
 __ZNK7WebCore16DeprecatedString2atEj
 __ZNK7WebCore16DeprecatedString3midEjj
+__ZNK7WebCore19SelectionController17isInPasswordFieldEv
 __ZNK7WebCore26NetscapePlugInStreamLoader6isDoneEv
 __ZNK7WebCore4Font11primaryFontEv
 __ZNK7WebCore4KURL8getNSURLEv
@@ -346,6 +345,14 @@ __ZNK7WebCore5Range12endContainerERi
 __ZNK7WebCore5Range19boundaryPointsValidEv
 __ZNK7WebCore5Range9endOffsetERi
 __ZNK7WebCore5Range9startNodeEv
+__ZNK7WebCore6Editor13canEditRichlyEv
+__ZNK7WebCore6Editor17shouldDeleteRangeEPNS_5RangeE
+__ZNK7WebCore6Editor17shouldDeleteRangeEPNS_5RangeE
+__ZNK7WebCore6Editor6canCutEv
+__ZNK7WebCore6Editor7canCopyEv
+__ZNK7WebCore6Editor7canEditEv
+__ZNK7WebCore6Editor8canPasteEv
+__ZNK7WebCore6Editor9canDeleteEv
 __ZNK7WebCore6String16deprecatedStringEv
 __ZNK7WebCore6String7isEmptyEv
 __ZNK7WebCore7Element12getAttributeERKNS_13QualifiedNameE
index 3dc9097ce4609e0d9095fad439d99dfb4c29761a..e1451c3980b1dc5cb9f7c5d26d851b42f6fdebf6 100644 (file)
@@ -37,7 +37,7 @@ class EditorClient : public Shared<EditorClient>{
 public:
     virtual ~EditorClient() { }
 
-    virtual bool shouldDeleteRange(Range *range) = 0;
+    virtual bool shouldDeleteRange(Range*) = 0;
     virtual bool shouldShowDeleteInterface(HTMLElement*) = 0;
     
     virtual bool isContinuousSpellCheckingEnabled() = 0;
index 73cc0e39a2199e01c2b718ac6614ab3a178fbcbd..70dda443c5f115821374c8e02d8f46f926a8634b 100644 (file)
@@ -191,9 +191,9 @@ public:
     void dragSourceMovedTo(const PlatformMouseEvent&);
     void dragSourceEndedAt(const PlatformMouseEvent&, NSDragOperation);
 
-    bool mayDHTMLCut();
-    bool mayDHTMLCopy();
-    bool mayDHTMLPaste();
+    bool canDHTMLCut();
+    bool canDHTMLCopy();
+    bool canDHTMLPaste();
     bool tryDHTMLCut();
     bool tryDHTMLCopy();
     bool tryDHTMLPaste();
@@ -285,7 +285,6 @@ public:
     
     virtual void handledOnloadEvents();
 
-    virtual bool canPaste() const;
     virtual bool canRedo() const;
     virtual bool canUndo() const;
     virtual void print();
index 919427035a937cde7718f9a9b514c899f5506cc0..8beb84a34ff11c442d769cab342b56fd450659a7 100644 (file)
@@ -1599,7 +1599,7 @@ void FrameMac::handleMouseMoveEvent(const MouseEventWithHitTestResults& event)
                         _dragClipboard->setDragImageElement(_dragSrc.get(), IntPoint() + delta);
                     } 
 
-                    setMouseDownMayStartDrag(dispatchDragSrcEvent(dragstartEvent, m_mouseDown) && mayCopy());
+                    setMouseDownMayStartDrag(dispatchDragSrcEvent(dragstartEvent, m_mouseDown) && !selectionController()->isInPasswordField());
                     // 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(ClipboardImageWritable);
@@ -1687,24 +1687,24 @@ bool FrameMac::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPo
 // 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::mayDHTMLCut()
+bool FrameMac::canDHTMLCut()
 {
-    return mayCopy() && !dispatchCPPEvent(beforecutEvent, ClipboardNumb);
+    return editor()->canCopy() && !dispatchCPPEvent(beforecutEvent, ClipboardNumb);
 }
 
-bool FrameMac::mayDHTMLCopy()
+bool FrameMac::canDHTMLCopy()
 {
-    return mayCopy() && !dispatchCPPEvent(beforecopyEvent, ClipboardNumb);
+    return editor()->canCopy() && !dispatchCPPEvent(beforecopyEvent, ClipboardNumb);
 }
 
-bool FrameMac::mayDHTMLPaste()
+bool FrameMac::canDHTMLPaste()
 {
     return !dispatchCPPEvent(beforepasteEvent, ClipboardNumb);
 }
 
 bool FrameMac::tryDHTMLCut()
 {
-    if (!mayCopy())
+    if (!editor()->canCopy())
         return false;
 
     // Must be done before oncut adds types and data to the pboard,
@@ -1716,7 +1716,7 @@ bool FrameMac::tryDHTMLCut()
 
 bool FrameMac::tryDHTMLCopy()
 {
-    if (!mayCopy())
+    if (!editor()->canCopy())
         return false;
 
     // Must be done before oncopy adds types and data to the pboard,
@@ -2499,11 +2499,6 @@ bool FrameMac::canRedo() const
     return [[Mac(this)->_bridge undoManager] canRedo];
 }
 
-bool FrameMac::canPaste() const
-{
-    return [Mac(this)->_bridge canPaste];
-}
-
 void FrameMac::markMisspellingsInAdjacentWords(const VisiblePosition &p)
 {
     if (!editor()->client()->isContinuousSpellCheckingEnabled())
index d426b787ac008f6bf47d296f540439c8b0fa96fa..ec86c63ab9408a20d05ee80a557b52a3758e107f 100644 (file)
@@ -75,12 +75,6 @@ typedef enum {
     WebCoreDevicePrinter
 } WebCoreDeviceType;
 
-typedef enum {
-    WebSelectionStateNone,
-    WebSelectionStateCaret,
-    WebSelectionStateRange
-} WebSelectionState;
-
 typedef enum {
     WebSelectByMoving,
     WebSelectByExtending
@@ -263,8 +257,6 @@ typedef enum {
 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture;
 - (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)string;
 
-- (BOOL)mayCopy;
-
 - (NSString *)selectedString;
 
 - (NSString *)stringForRange:(DOMRange *)range;
@@ -311,7 +303,6 @@ typedef enum {
 - (WebBridgeSelectionGranularity)selectionGranularity;
 - (DOMRange *)smartDeleteRangeForProposedRange:(DOMRange *)proposedCharRange;
 - (void)smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)charRangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString;
-- (BOOL)canDeleteRange:(DOMRange *)range;
 - (void)selectNSRange:(NSRange)range;
 - (NSRange)selectedNSRange;
 - (NSRange)markedTextNSRange;
@@ -502,7 +493,6 @@ typedef enum {
 - (BOOL)shouldEndEditing:(DOMRange *)range;
 - (void)didBeginEditing;
 - (void)didEndEditing;
-- (BOOL)canPaste;
 
 - (NSString *)overrideMediaType;
 
index cc40ddfea5df11cb928a20f4537816464cb99216..fa3fc5367f4d683b2b02c5d691852c9ac65205a9 100644 (file)
@@ -246,46 +246,6 @@ static inline WebCoreFrameBridge *bridge(Frame *frame)
     return nil;
 }
 
-#if 0
-// FIXME: This is not getting called any more! security regression!?
-- (BOOL)_shouldAllowAccessFrom:(WebCoreFrameBridge *)source
-{
-    // if no source frame, allow access
-    if (source == nil)
-        return YES;
-
-    //   - allow access if the two frames are in the same window
-    if ([self page] == [source page])
-        return YES;
-
-    //   - allow if the request is made from a local file.
-    NSString *sourceDomain = [self domain];
-    if ([sourceDomain length] == 0)
-        return YES;
-
-    //   - allow access if this frame or one of its ancestors
-    //     has the same origin as source
-    for (WebCoreFrameBridge *ancestor = self; ancestor; ancestor = [ancestor parent]) {
-        NSString *ancestorDomain = [ancestor domain];
-        if (ancestorDomain != nil && 
-            isCaseSensitiveEqual(sourceDomain, ancestorDomain))
-            return YES;
-    }
-
-    //   - allow access if this frame is a toplevel window and the source
-    //     can access its opener. Note that we only allow one level of
-    //     recursion here.
-    if ([self parent] == nil) {
-        NSString *openerDomain = [[self opener] domain];
-        if (openerDomain != nil && isCaseSensitiveEqual(sourceDomain, openerDomain))
-            return YES;
-    }
-    
-    // otherwise deny access
-    return NO;
-}
-#endif
-
 + (NSArray *)supportedNonImageMIMETypes
 {
     return [NSArray arrayWithObjects:        
@@ -491,26 +451,6 @@ static inline WebCoreFrameBridge *bridge(Frame *frame)
         frameView->setMarginHeight(mh);
 }
 
-- (WebSelectionState)selectionState
-{
-    switch (m_frame->selectionController()->state()) {
-        case WebCore::Selection::NONE:
-            return WebSelectionStateNone;
-        case WebCore::Selection::CARET:
-            return WebSelectionStateCaret;
-        case WebCore::Selection::RANGE:
-            return WebSelectionStateRange;
-    }
-    
-    ASSERT_NOT_REACHED();
-    return WebSelectionStateNone;
-}
-
-- (BOOL)mayCopy
-{
-    return m_frame->mayCopy();
-}
-
 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
 {
     return m_frame->documentTypeString() + markupString;
@@ -1106,7 +1046,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (DOMRange *)rangeByAlteringCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return nil;
 
     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
@@ -1120,7 +1060,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration direction:(WebBridgeSelectionDirection)direction granularity:(WebBridgeSelectionGranularity)granularity
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
 
     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h
@@ -1132,7 +1072,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)alterCurrentSelection:(WebSelectionAlteration)alteration verticalDistance:(float)verticalDistance
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     SelectionController* selectionController = m_frame->selectionController();
     selectionController->modify(static_cast<SelectionController::EAlter>(alteration), static_cast<int>(verticalDistance), true);
@@ -1236,7 +1176,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)replaceMarkedTextWithText:(NSString *)text
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     
     int exception = 0;
@@ -1251,27 +1191,6 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
     m_frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
 }
 
-- (BOOL)canDeleteRange:(DOMRange *)range
-{
-    Node *startContainer = [[range startContainer] _node];
-    Node *endContainer = [[range endContainer] _node];
-    if (startContainer == nil || endContainer == nil)
-        return NO;
-    
-    if (!startContainer->isContentEditable() || !endContainer->isContentEditable())
-        return NO;
-    
-    if ([range collapsed]) {
-        VisiblePosition start(startContainer, [range startOffset], DOWNSTREAM);
-        VisiblePosition previous = start.previous();
-        // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
-        if (previous.isNull() || previous.deepEquivalent().node()->rootEditableElement() != startContainer->rootEditableElement())
-            return NO;
-    }
-    
-    return YES;
-}
-
 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
 // the text surrounding the deletion.
@@ -1389,7 +1308,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
 {
-    if (!m_frame->hasSelection() || !fragment)
+    if (m_frame->selectionController()->isNone() || !fragment)
         return;
     
     applyCommand(new ReplaceSelectionCommand(m_frame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle));
@@ -1428,7 +1347,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (DOMNode *)increaseSelectionListLevel;
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return nil;
     
     Node* newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(m_frame->document());
@@ -1438,7 +1357,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (DOMNode *)increaseSelectionListLevelOrdered;
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return nil;
     
     Node* newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(m_frame->document());
@@ -1448,7 +1367,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (DOMNode *)increaseSelectionListLevelUnordered;
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return nil;
     
     Node* newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(m_frame->document());
@@ -1458,7 +1377,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)decreaseSelectionListLevel
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     
     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(m_frame->document());
@@ -1467,7 +1386,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)insertLineBreak
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     
     TypingCommand::insertLineBreak(m_frame->document());
@@ -1476,7 +1395,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)insertParagraphSeparator
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     
     TypingCommand::insertParagraphSeparator(m_frame->document());
@@ -1485,7 +1404,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)insertParagraphSeparatorInQuotedContent
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     
     TypingCommand::insertParagraphSeparatorInQuotedContent(m_frame->document());
@@ -1494,7 +1413,7 @@ static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
 
 - (void)insertText:(NSString *)text selectInsertedText:(BOOL)selectInsertedText
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     
     TypingCommand::insertText(m_frame->document(), text, selectInsertedText);
index 924b8c7ede3a6c9f0901e162e4e2c38ca9137835..4261dbb0e45931d94434a7809437411e432d670d 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <wtf/HashMap.h>
 #include "Document.h"
+#include "Editor.h"
 #include "Frame.h"
 #include "PlatformString.h"
 #include "SelectionController.h"
@@ -168,7 +169,7 @@ bool enabledAnyEditableSelection(Frame* frame)
 
 bool enabledPaste(Frame* frame)
 {
-    return supportsPasteCommand && frame->canPaste();
+    return supportsPasteCommand && frame->editor()->canPaste();
 }
 
 bool enabledAnyRangeSelection(Frame* frame)
index ab2fb852b8cdc5bcbdc8c2ec2f902ab038195fd7..0d1221a324b956ac6bba7e1ce0215ab8d08bb216 100644 (file)
@@ -60,22 +60,42 @@ EditorClient* Editor::client() const
     return m_client.get();
 }
 
-bool Editor::canCopy()
+bool Editor::canEdit() const
 {
-    return false;
+    SelectionController* selectionController = m_frame->selectionController();
+    return selectionController->isCaretOrRange() && selectionController->isContentEditable();
 }
 
-bool Editor::canCut()
+bool Editor::canEditRichly() const
 {
-    return false;
+    SelectionController* selectionController = m_frame->selectionController();
+    return canEdit() && selectionController->isContentRichlyEditable();
 }
 
-bool Editor::canDelete()
+bool Editor::canCut() const
 {
-    return false;
+    return canCopy() && canDelete();
+}
+
+bool Editor::canCopy() const
+{
+    SelectionController* selectionController = m_frame->selectionController();
+    return selectionController->isRange() && !selectionController->isInPasswordField();
+}
+
+bool Editor::canPaste() const
+{
+    SelectionController* selectionController = m_frame->selectionController();
+    return selectionController->isCaretOrRange() && selectionController->isContentEditable();
+}
+
+bool Editor::canDelete() const
+{
+    SelectionController* selectionController = m_frame->selectionController();
+    return selectionController->isRange() && selectionController->isContentEditable();
 }
 
-bool Editor::canDeleteRange(Range* range)
+bool Editor::canDeleteRange(Range* range) const
 {
     ExceptionCode ec = 0;
     Node* startContainer = range->startContainer(ec);
@@ -96,11 +116,6 @@ bool Editor::canDeleteRange(Range* range)
     return true;
 }
 
-bool Editor::canPaste()
-{
-    return false;
-}
-
 bool Editor::canSmartCopyOrDelete()
 {
     return false;
@@ -112,17 +127,12 @@ void Editor::deleteSelection()
 
 void Editor::deleteSelectionWithSmartDelete(bool smartDelete)
 {
-    if (!m_frame->hasSelection())
+    if (m_frame->selectionController()->isNone())
         return;
     
     applyCommand(new DeleteSelectionCommand(m_frame->document(), smartDelete));
 }
 
-bool Editor::isSelectionRichlyEditable()
-{
-    return false;
-}
-
 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard pasteboard)
 {
 }
@@ -136,7 +146,7 @@ Range* Editor::selectedRange()
     return 0;
 }
 
-bool Editor::shouldDeleteRange(Range* range)
+bool Editor::shouldDeleteRange(Range* range) const
 {
     ExceptionCode ec;
     if (!range || range->collapsed(ec))
@@ -170,7 +180,7 @@ void Editor::writeSelectionToPasteboard(Pasteboard pasteboard)
 {
 }
 
-bool Editor::shouldShowDeleteInterface(HTMLElement* element)
+bool Editor::shouldShowDeleteInterface(HTMLElement* element) const
 {
     return m_client->shouldShowDeleteInterface(element);
 }
@@ -298,7 +308,7 @@ void Editor::paste()
         return;     // DHTML did the whole operation
     if (!canPaste())
         return;
-    if (isSelectionRichlyEditable())
+    if (canEditRichly())
         pasteWithPasteboard(generalPasteboard(), true);
     else
         pasteAsPlainTextWithPasteboard(generalPasteboard());
index 1fc988412d28e7dd698d1f406fa2e554065966c2..ed28e3ab03916316f5757e1f832b783f87fd9214 100644 (file)
@@ -50,13 +50,25 @@ public:
     ~Editor();
 
     EditorClient* client() const;
+    Frame* frame() const { return m_frame; }
+    DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
+    EditCommand* lastEditCommand() { return m_lastEditCommand.get(); }
+    
+    bool canEdit() const;
+    bool canEditRichly() const;
 
+    bool canCut() const;
+    bool canCopy() const;
+    bool canPaste() const;
+    bool canDelete() const;
+    
     void cut();
     void copy();
     void paste();
     void performDelete();
 
-    bool shouldShowDeleteInterface(HTMLElement*);
+    bool shouldShowDeleteInterface(HTMLElement*) const;
+    bool shouldDeleteRange(Range*) const;
 
     void respondToChangedSelection(const Selection& oldSelection);
     void respondToChangedContents();
@@ -66,10 +78,6 @@ public:
     
     void removeFormattingAndStyle();
 
-    Frame* frame() const { return m_frame; }
-    DeleteButtonController* deleteButtonController() const { return m_deleteButtonController.get(); }
-    EditCommand* lastEditCommand() { return m_lastEditCommand.get(); }
-
     // FIXME: Once the Editor implements all editing commands, it should track 
     // the lastEditCommand on its own, and we should remove this function.
     void setLastEditCommand(PassRefPtr<EditCommand> lastEditCommand);
@@ -82,15 +90,9 @@ private:
     OwnPtr<DeleteButtonController> m_deleteButtonController;
     RefPtr<EditCommand> m_lastEditCommand;
 
-    bool canCopy();
-    bool canCut();
-    bool canDelete();
-    bool canDeleteRange(Range*);
-    bool canPaste();
+    bool canDeleteRange(Range*) const;
     bool canSmartCopyOrDelete();
-    bool isSelectionRichlyEditable();
     Range* selectedRange();
-    bool shouldDeleteRange(Range*);
     bool tryDHTMLCopy();
     bool tryDHTMLCut();
     bool tryDHTMLPaste();
index 1925e3bb588e4800c997f1957898c2bf365b268c..450ad0840ff45cc2c84ecbcc96ddc8ef9376695b 100644 (file)
@@ -506,12 +506,12 @@ bool enabledAnyRichlyEditableSelection(Frame* frame)
 
 bool enabledPaste(Frame* frame)
 {
-    return supportsPasteCommand && frame->canPaste();
+    return supportsPasteCommand && frame->editor()->canPaste();
 }
 
 bool enabledPasteAndMatchStyle(Frame* frame)
 {
-    return supportsPasteCommand && frame->canPaste();
+    return supportsPasteCommand && frame->editor()->canPaste();
 }
 
 bool enabledAnyRangeSelection(Frame* frame)
index d3e0b4b019137c43594abfa1c787c8f8e06dcbce..f17596a97ea01553c1c6c63eca799c765ab32d85 100644 (file)
@@ -34,6 +34,8 @@
 #include "Frame.h"
 #include "FrameTree.h"
 #include "GraphicsContext.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
 #include "RenderView.h"
@@ -47,6 +49,7 @@
 namespace WebCore {
 
 using namespace EventNames;
+using namespace HTMLNames;
 
 SelectionController::SelectionController(Frame* frame, bool isDragCaretController)
     : m_needsLayout(true)
@@ -1074,6 +1077,22 @@ void SelectionController::setSelectedRange(Range* range, EAffinity affinity, boo
     setSelection(Selection(visibleStart, visibleEnd), closeTyping);
 }
 
+bool SelectionController::isInPasswordField() const
+{
+    Node* startNode = start().node();
+    if (!startNode)
+        return false;
+
+    startNode = startNode->shadowAncestorNode();
+    if (!startNode)
+        return false;
+
+    if (!startNode->hasTagName(inputTag))
+        return false;
+    
+    return static_cast<HTMLInputElement*>(startNode)->inputType() == HTMLInputElement::PASSWORD;
+}
+  
 #ifndef NDEBUG
 
 void SelectionController::formatForDebugger(char* buffer, unsigned length) const
index cd913bc3095f33fd32a0fdc84726abf7c9818b76..4cf2dce1cc19ddda196d26f09e2d38c8a39d6fc1 100644 (file)
@@ -45,9 +45,9 @@ public:
 
     SelectionController(Frame* = 0, bool isDragCaretController = false);
 
-    Element* rootEditableElement() const { return selection().rootEditableElement(); }
-    bool isContentEditable() const { return selection().isContentEditable(); }
-    bool isContentRichlyEditable() const { return selection().isContentRichlyEditable(); }
+    Element* rootEditableElement() const { return m_sel.rootEditableElement(); }
+    bool isContentEditable() const { return m_sel.isContentEditable(); }
+    bool isContentRichlyEditable() const { return m_sel.isContentRichlyEditable(); }
 
     void moveTo(const Range*, EAffinity, bool userTriggered = false);
     void moveTo(const VisiblePosition&, bool userTriggered = false);
@@ -94,6 +94,7 @@ public:
     bool isCaret() const { return m_sel.isCaret(); }
     bool isRange() const { return m_sel.isRange(); }
     bool isCaretOrRange() const { return m_sel.isCaretOrRange(); }
+    bool isInPasswordField() const;
 
     PassRefPtr<Range> toRange() const { return m_sel.toRange(); }
 
index cc56b7ae19db7c319e28af7f4b5f915423d73caa..4fe728e2d2b32034ed4a2a7c2558adcbe37b841a 100644 (file)
@@ -1408,11 +1408,6 @@ String Frame::selectedText() const
     return plainText(selectionController()->toRange().get());
 }
 
-bool Frame::hasSelection() const
-{
-    return selectionController()->isCaretOrRange();
-}
-
 SelectionController* Frame::selectionController() const
 {
     return &d->m_selectionController;
@@ -2043,14 +2038,6 @@ void Frame::textDidChangeInTextArea(Element* input)
 {
 }
 
-bool Frame::isSelectionInPasswordField()
-{
-    Node* startNode = selectionController()->start().node();
-    if (startNode)
-        startNode = startNode->shadowAncestorNode();
-    return startNode && startNode->hasTagName(inputTag) && static_cast<HTMLInputElement*>(startNode)->inputType() == HTMLInputElement::PASSWORD;
-}
-  
 static void dispatchEditableContentChangedEvents(const EditCommand& command)
 {
      Element* startRoot = command.startingRootEditableElement();
@@ -2204,11 +2191,6 @@ void Frame::pasteAndMatchStyle()
     issuePasteAndMatchStyleCommand();
 }
 
-bool Frame::mayCopy()
-{
-    return !isSelectionInPasswordField();
-}
-
 void Frame::transpose()
 {
     issueTransposeCommand();
@@ -2732,7 +2714,7 @@ void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
 
 void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
 {
-    if (!hasSelection())
+    if (selectionController()->isNone())
         return;
 
     Position extent = selectionController()->extent();
@@ -2839,16 +2821,6 @@ HitTestResult Frame::hitTestResultAtPoint(const IntPoint& point, bool allowShado
     return result;
 }
 
-bool Frame::hasSelection()
-{
-    if (selectionController()->isNone())
-        return false;
-
-    // If a part has a selection, it should also have a document.        
-    ASSERT(document());
-
-    return true;
-}
 
 void Frame::startAutoscrollTimer()
 {
index cc485f70e6acbc0e80ba636ee81d118d4ae85d4d..416c9dad489f9ea406b090c2b51c21b96f356286 100644 (file)
@@ -372,16 +372,6 @@ public:
    */
   int xPosForVerticalArrowNavigation() const;
 
-  /**
-   * Has the user selected anything?
-   *
-   *  Call @ref selectedText() to
-   * retrieve the selected text.
-   *
-   * @return @p true if there is text selected.
-   */
-  bool hasSelection() const;
-
   /**
    * Returns whether editing should end in the given range
    */
@@ -419,8 +409,6 @@ public:
   virtual void setSecureKeyboardEntry(bool) {};
   virtual bool isSecureKeyboardEntry() { return false; }
   
-  bool isSelectionInPasswordField();
-  
   /**
    * Called when editing has been applied.
    */
@@ -482,8 +470,6 @@ public:
   void cutToPasteboard();
   void pasteFromPasteboard();
   void pasteAndMatchStyle();
-  bool mayCopy();
-  virtual bool canPaste() const = 0;
   void redo();
   void undo();
   virtual bool canRedo() const = 0;
@@ -767,7 +753,6 @@ public:
   friend class FrameWin;
 
   HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent);
-  bool hasSelection();
   String documentTypeString() const;
 
   void checkEmitLoadEvent();
index fca8a89a9621ae515420cc330720359c17814977..b0bbd74172793e32bc937bd8561751866ab6a76f 100644 (file)
@@ -683,7 +683,7 @@ static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
 static Cursor selectCursor(const MouseEventWithHitTestResults& event, Frame* frame, bool mousePressed, PlatformScrollbar* scrollbar)
 {
     // During selection, use an I-beam no matter what we're over.
-    if (mousePressed && frame->hasSelection())
+    if (mousePressed && frame->selectionController()->isCaretOrRange())
         return iBeamCursor();
 
     Node* node = event.targetNode();
index 1df22949b67f76967fecfcfee4fc64b0a7e522ec..7329df08cf8ac46900229b83b0509133c54d3d00 100644 (file)
@@ -1,3 +1,24 @@
+2006-10-31  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Alice.
+        
+        Moved some Editing code from WebKit, the bridge, and WebCore::Frame down 
+        to WebCore::Editor.
+
+        * WebCoreSupport/WebFrameBridge.mm:
+        * WebView/WebHTMLView.m:
+        (-[WebHTMLView _shouldDeleteRange:]):
+        (-[WebHTMLView _canCopy]):
+        (-[WebHTMLView _canCut]):
+        (-[WebHTMLView _canDelete]):
+        (-[WebHTMLView _canPaste]):
+        (-[WebHTMLView _canEdit]):
+        (-[WebHTMLView _canEditRichly]):
+        (-[WebHTMLView _isEditable]):
+        (-[WebHTMLView _isSelectionInPasswordField]):
+        (-[NSArray validateUserInterfaceItem:]):
+        (-[NSArray _expandSelectionToGranularity:]):
+
 2006-10-31  John Sullivan  <sullivan@apple.com>
 
         Reviewed by Beth and Adam
index 33b0af22ec3bd3080d432f96f5bba5d811d66f9c..21e7d75d039af1ff3c85577fe435e39a885c97f4 100644 (file)
@@ -1174,12 +1174,6 @@ static id <WebFormDelegate> formDelegate(WebFrameBridge *self)
         [(WebHTMLView *)view transpose:nil];
 }
 
-- (BOOL)canPaste
-{
-    NSView* documentView = [[_frame frameView] documentView];
-    return [documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView*)documentView _canPaste];
-}
-
 - (void)setIsSelected:(BOOL)isSelected forView:(NSView *)view
 {
     if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)]) {
index e159d24aab241d981a92ebc033915887830896ba..94b7a3e25bc1f166836dd2ae6072182b8f0ad9ec 100644 (file)
@@ -597,14 +597,10 @@ extern "C" void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFramework
 
 - (BOOL)_shouldDeleteRange:(DOMRange *)range
 {
-    if (range == nil || [range collapsed])
-        return NO;
-    
-    if (![[self _bridge] canDeleteRange:range])
-        return NO;
-        
-    WebView *webView = [self _webView];
-    return [[webView _editingDelegateForwarder] webView:webView shouldDeleteDOMRange:range];
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return nil;
+    return coreFrame->editor()->shouldDeleteRange(core(range));
 }
 
 - (void)_deleteRange:(DOMRange *)range 
@@ -1622,28 +1618,42 @@ static WebHTMLView *lastHitView = nil;
 
 - (BOOL)_canCopy
 {
-    // Copying can be done regardless of whether you can edit.
-    return [self _hasSelection] && [[self _bridge] mayCopy];
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return false;
+    return coreFrame->editor()->canCopy();
 }
 
 - (BOOL)_canCut
 {
-    return [self _canCopy] && [self _isEditable];
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return false;
+    return coreFrame->editor()->canCut();
 }
 
 - (BOOL)_canDelete
 {
-    return [self _hasSelection] && [self _isEditable];
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return false;
+    return coreFrame->editor()->canDelete();
 }
 
 - (BOOL)_canPaste
 {
-    return [self _hasSelectionOrInsertionPoint] && [self _isEditable];
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return false;
+    return coreFrame->editor()->canPaste();
 }
 
 - (BOOL)_canEdit
 {
-    return [self _hasSelectionOrInsertionPoint] && [self _isEditable];
+    Frame* coreFrame = core([self _frame]);
+    if (!coreFrame)
+        return false;
+    return coreFrame->editor()->canEdit();
 }
 
 - (BOOL)_canEditRichly
@@ -1651,7 +1661,7 @@ static WebHTMLView *lastHitView = nil;
     Frame* coreFrame = core([self _frame]);
     if (!coreFrame)
         return NO;
-    return [self _canEdit] && coreFrame->selectionController()->isContentRichlyEditable();
+    return coreFrame->editor()->canEditRichly();
 }
 
 - (BOOL)_canAlterCurrentSelection
@@ -1685,10 +1695,10 @@ static WebHTMLView *lastHitView = nil;
 
 - (BOOL)_isEditable
 {
-    Frame* coreFrame = core([self _frame]);
+    FrameMac* coreFrame = core([self _frame]);
     if (!coreFrame)
         return NO;
-    return [[self _webView] isEditable] || coreFrame->selectionController()->isContentEditable();
+    return coreFrame->selectionController()->isContentEditable();
 }
 
 - (BOOL)_isSelectionInPasswordField
@@ -1696,7 +1706,7 @@ static WebHTMLView *lastHitView = nil;
     Frame* coreFrame = core([self _frame]);
     if (!coreFrame)
         return NO;
-    return coreFrame->isSelectionInPasswordField();
+    return coreFrame->selectionController()->isInPasswordField();
 }
 
 - (BOOL)_isSelectionMisspelled
@@ -2273,10 +2283,10 @@ static WebHTMLView *lastHitView = nil;
         return [[self _webView] isEditable] && [self _canEditRichly];
     
     if (action == @selector(copy:))
-        return (frame && frame->mayDHTMLCopy()) || [self _canCopy];
+        return (frame && frame->canDHTMLCopy()) || [self _canCopy];
     
     if (action == @selector(cut:))
-        return (frame && frame->mayDHTMLCut()) || [self _canCut];
+        return (frame && frame->canDHTMLCut()) || [self _canCut];
     
     if (action == @selector(delete:))
         return [self _canDelete];
@@ -2287,10 +2297,10 @@ static WebHTMLView *lastHitView = nil;
         return [self _hasSelection];
     
     if (action == @selector(paste:) || action == @selector(pasteAsPlainText:))
-        return (frame && frame->mayDHTMLPaste()) || [self _canPaste];
+        return (frame && frame->canDHTMLPaste()) || [self _canPaste];
     
     if (action == @selector(pasteAsRichText:))
-        return frame && (frame->mayDHTMLPaste()
+        return frame && (frame->canDHTMLPaste()
             || ([self _canPaste] && frame->selectionController()->isContentRichlyEditable()));
     
     if (action == @selector(performFindPanelAction:))
@@ -3795,7 +3805,7 @@ done:
         return;
     
     Frame* coreFrame = core([self _frame]);
-    if (!coreFrame || !coreFrame->hasSelection())
+    if (!coreFrame || !coreFrame->selectionController()->isCaretOrRange())
         return;
 
     // NOTE: The enums *must* match the very similar ones declared in SelectionController.h