WebCore:
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Mar 2008 17:21:55 +0000 (17:21 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Mar 2008 17:21:55 +0000 (17:21 +0000)
        Reviewed by Mitz.

        - fix http://bugs.webkit.org/show_bug.cgi?id=17526
          REGRESSION: iframes are added to Safari's History menu
          by separating the visited link machinery from global history

        This should also make page loading faster due to more efficient visited link coloring.

        * WebCore.base.exp: Updated.
        * WebCore.vcproj/WebCore.vcproj: Added PageGroup.h/cpp, removed GlobalHistory.h/cpp.
        * WebCore.xcodeproj/project.pbxproj: Ditto. Also removed WebCoreHistory.h/m.

        * css/CSSStyleSelector.cpp: Updated includes.
        (WebCore::CSSStyleSelector::initElementAndPseudoState): Eliminated code to set
        currentEncodedURL.
        (WebCore::checkPseudoState): Moved most of the code inside a new
        PageGroup::isLinkVisited function.
        (WebCore::CSSStyleSelector::canShareStyleWithElement): Tightened code a bit by using
        references and only getting colors when needed.
        (WebCore::CSSStyleSelector::getColorFromPrimitiveValue): Ditto.
        * css/CSSStyleSelector.h: Removed EncodedURL, m_encodedURL, and setEncodedURL.

        * dom/Document.cpp:
        (WebCore::Document::attach): Removed call to setEncodedURL.
        (WebCore::Document::setURL): Ditto.
        (WebCore::Document::recalcStyleSelector): Ditto.

        * loader/FrameLoader.cpp:
        (WebCore::FrameLoader::addBackForwardItemClippedAtTarget): Changed code to use
        early exit idiom to be a little more readable.
        (WebCore::FrameLoader::urlsMatchItem): Change to use a reference for slightly
        better efficiency.
        (WebCore::FrameLoader::goToItem): Use early exit idiom to be a little more
        readable.
        (WebCore::FrameLoader::updateHistoryForStandardLoad): Moved history code back
        in here and got rid of the helper function updateGlobalHistory, restoring the
        logic before r30549. Also added a call to the new addVisitedLink function.
        (WebCore::FrameLoader::updateHistoryForClientRedirect): Added code to call
        addVisitedLink here.
        (WebCore::FrameLoader::updateHistoryForBackForwardNavigation): Removed comment.
        (WebCore::FrameLoader::updateHistoryForReload): Removed call to
        updateGlobalHistory; we can just go without updating global history or
        visited links here, at least for now, since it's not clear that a reload
        is a "history event".
        (WebCore::FrameLoader::updateHistoryForRedirectWithLockedHistory): Moved
        history code back where it was, and added the call to addVisitedLink, just
        as in updateHistoryForStandardLoad above.
        * loader/FrameLoader.h: Removed updateGlobalHistory function.

        * page/Chrome.cpp:
        (WebCore::ChromeClient::populateVisitedLinks): Added. Empty placeholder so we
        don't have to implement this for every port all at once.
        (WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer): Changed to use the
        new PageGroup class.
        * page/ChromeClient.h: Added populateVisitedLinks function, used to fill the
        visited links set from the global history at application startup time.

        * page/FrameTree.cpp:
        (WebCore::FrameTree::find): Updated to use the new PageGroup class.

        * page/GlobalHistory.h: Removed.
        * page/win/GlobalHistoryWin.cpp: Removed.
        * page/mac/GlobalHistoryMac.mm: Removed.
        * platform/mac/WebCoreHistory.h: Removed.
        * platform/mac/WebCoreHistory.m: Removed.
        * platform/win/WebCoreHistory.cpp: Removed.
        * platform/win/WebCoreHistory.h: Removed.

        * page/Page.cpp:
        (WebCore::Page::Page): Set m_group to 0.
        (WebCore::Page::setGroupName): Set up m_group. If the page is not in any
        group, set it to 0 for now to postpone the cost of creating a group.
        (WebCore::Page::initGroup): Added. Sets m_group to point to a single-page
        group; used when getting a group.
        (WebCore::Page::removeAllVisitedLinks): Added. Calls removeVisitedLinks
        on all page groups.
        * page/Page.h: Moved enums inside the WebCore namespace. Removed the
        frameNamespace function and instead added the group and groupPtr functions.

        * page/PageGroup.cpp: Added. Contains all the visited code from the
        CSSStyleSelector in the isVisitedLink function, but more efficient because
        we don't allocate memory for the buffer.
        * page/PageGroup.h: Added.

        * platform/gtk/TemporaryLinkStubs.cpp: Removed historyContains.
        * platform/qt/TemporaryLinkStubs.cpp: Removed unneeded include.
        * platform/wx/TemporaryLinkStubs.cpp: Removed historyContains.

WebKit:

        * WebKit.xcodeproj/project.pbxproj: Added WebHistoryInternal.h.

WebKit/mac:

        Reviewed by Mitz.

        - fix http://bugs.webkit.org/show_bug.cgi?id=17526
          REGRESSION: iframes are added to Safari's History menu
          by separating the visited link machinery from global history

        * History/WebHistory.mm: Moved WebHistoryPrivate inside this file.
        (-[WebHistoryPrivate removeItemFromDateCaches:]): Removed the underscore from this
        method name, since it's on a private object.
        (-[WebHistoryPrivate removeItemForURLString:]): Added a call to the
        PageGroup::removeAllVisitedLinks function if the last URL was removed.
        (-[WebHistoryPrivate addItemToDateCaches:]): Removed the underscore from this
        method name, since it's on a private object.
        (-[WebHistoryPrivate removeAllItems]): Call PageGroup::removeAllVisitedLinks.
        (-[WebHistoryPrivate ageLimitDate]): Removed the underscore from this
        method name, since it's on a private object.
        (-[WebHistoryPrivate loadHistoryGutsFromURL:savedItemsCount:collectDiscardedItemsInto:error:]):
        Ditto.
        (-[WebHistoryPrivate saveHistoryGuts:URL:error:]): Ditto. Also changed this
        to correctly return the error by using the newer version of writeToURL: and
        removed the FIXME about that.
        (-[WebHistoryPrivate addVisitedLinksToPageGroup:]): Added. Calls addVisitedLink
        for every link in the history.
        (-[WebHistory saveToURL:error:]): Removed the FIXME, since we do get the error now.
        (-[WebHistory addItem:]): Moved into the WebPrivate category.
        (-[WebHistory addItemForURL:]): Ditto.
        (-[WebHistory _addItemForURL:title:]): Added. Used for the normal case where we
        create an item and already know its title.
        (-[WebHistory ageLimitDate]): Moved into the WebPrivate category.
        (-[WebHistory containsItemForURLString:]): Ditto.
        (-[WebHistory removeItem:]): Ditto.
        (-[WebHistory setLastVisitedTimeInterval:forItem:]): Ditto.
        (-[WebHistory _itemForURLString:]): Ditto.
        (-[WebHistory _addVisitedLinksToPageGroup:]): Added. For use only inside WebKit.

        * History/WebHistoryInternal.h: Added.
        * History/WebHistoryItemInternal.h: Tweaked formatting and includes.
        * History/WebHistoryPrivate.h: Moved the WebHistoryPrivate class out of this header.
        Also reorganized what was left behind.

        * WebCoreSupport/WebChromeClient.h: Added populateVisitedLinks.
        * WebCoreSupport/WebChromeClient.mm:
        (WebChromeClient::populateVisitedLinks): Added a call to the new
        -[WebHistory _addVisitedLinksToPageGroup:] method.

        * WebCoreSupport/WebFrameLoaderClient.mm:
        (WebFrameLoaderClient::updateGlobalHistory): Changed code to use the new
        -[WebHistory _addItemForURL:title:] method.

WebKit/win:

        Reviewed by Mitz.

        - fix http://bugs.webkit.org/show_bug.cgi?id=17526
          REGRESSION: iframes are added to Safari's History menu
          by separating the visited link machinery from global history

        * WebCoreSupport/WebChromeClient.cpp:
        (WebChromeClient::populateVisitedLinks): Added a call to the new
        WebHistory::addVisitedLinksToPageGroup function.
        * WebCoreSupport/WebChromeClient.h: Added populateVisitedLinks.
        Also fixed the webView function to be non-virtual.

        * WebCoreSupport/WebFrameLoaderClient.cpp:
        (WebFrameLoaderClient::updateGlobalHistory): Changed to use the
        new WebHistory::addItem function.
        (WebFrameLoaderClient::webHistory): Changed to return a WebHistory*,
        there's no reason to AddRef the result from this function.
        * WebCoreSupport/WebFrameLoaderClient.h: Ditto.

        * WebHistory.cpp: Removed IWebHistoryPrivate and _WebCoreHistoryProvider.
        (WebHistory::QueryInterface): Removed IWebHistoryPrivate.
        (sharedHistoryStorage): Added.
        (WebHistory::sharedHistory): Added.
        (WebHistory::optionalSharedHistory): Changed to use sharedHistory().
        (WebHistory::setOptionalSharedHistory): Changed to require a WebHistory
        object, not just an IWebHistory.
        (WebHistory::removeAllItems): Call PageGroup::removeAllVisitedLinks.
        (WebHistory::addItem): Changed parameter types since this is called with
        arguments from WebCore -- at some point this could allow better efficiency.
        (WebHistory::removeItemForURLString):  Call PageGroup::removeAllVisitedLinks
        if the last URL is being removed.
        (addVisitedLinkToPageGroup): Added. Helper. Adds a single link to a group's
        visited link set.
        (WebHistory::addVisitedLinksToPageGroup): Added. Adds all links to a group's
        visited link.
        * WebHistory.h: Removed IWebHistoryPrivate. Removed optionalSharedHistoryInternal
        and added sharedHistory. Replaced addItemForURL and containsItemForURLString with
        non-virtual addItem and addVisitedLinksToPageGroup functions.

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

42 files changed:
WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/css/CSSStyleSelector.cpp
WebCore/css/CSSStyleSelector.h
WebCore/dom/Document.cpp
WebCore/loader/FrameLoader.cpp
WebCore/loader/FrameLoader.h
WebCore/page/Chrome.cpp
WebCore/page/ChromeClient.h
WebCore/page/FrameTree.cpp
WebCore/page/Page.cpp
WebCore/page/Page.h
WebCore/page/PageGroup.cpp [new file with mode: 0644]
WebCore/page/PageGroup.h [moved from WebCore/page/GlobalHistory.h with 56% similarity]
WebCore/page/mac/GlobalHistoryMac.mm [deleted file]
WebCore/page/win/GlobalHistoryWin.cpp [deleted file]
WebCore/platform/gtk/TemporaryLinkStubs.cpp
WebCore/platform/mac/WebCoreHistory.h [deleted file]
WebCore/platform/mac/WebCoreHistory.m [deleted file]
WebCore/platform/qt/TemporaryLinkStubs.cpp
WebCore/platform/win/WebCoreHistory.cpp [deleted file]
WebCore/platform/win/WebCoreHistory.h [deleted file]
WebCore/platform/wx/TemporaryLinkStubs.cpp
WebKit/ChangeLog
WebKit/WebKit.xcodeproj/project.pbxproj
WebKit/mac/ChangeLog
WebKit/mac/History/WebHistory.mm
WebKit/mac/History/WebHistoryInternal.h [new file with mode: 0644]
WebKit/mac/History/WebHistoryItemInternal.h
WebKit/mac/History/WebHistoryPrivate.h
WebKit/mac/WebCoreSupport/WebChromeClient.h
WebKit/mac/WebCoreSupport/WebChromeClient.mm
WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm
WebKit/win/ChangeLog
WebKit/win/WebCoreSupport/WebChromeClient.cpp
WebKit/win/WebCoreSupport/WebChromeClient.h
WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp
WebKit/win/WebCoreSupport/WebFrameLoaderClient.h
WebKit/win/WebHistory.cpp
WebKit/win/WebHistory.h

index 9119a5b..34c0957 100644 (file)
@@ -1,3 +1,93 @@
+2008-03-06  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mitz.
+
+        - fix http://bugs.webkit.org/show_bug.cgi?id=17526
+          REGRESSION: iframes are added to Safari's History menu
+          by separating the visited link machinery from global history
+
+        This should also make page loading faster due to more efficient visited link coloring.
+
+        * WebCore.base.exp: Updated.
+        * WebCore.vcproj/WebCore.vcproj: Added PageGroup.h/cpp, removed GlobalHistory.h/cpp.
+        * WebCore.xcodeproj/project.pbxproj: Ditto. Also removed WebCoreHistory.h/m.
+
+        * css/CSSStyleSelector.cpp: Updated includes.
+        (WebCore::CSSStyleSelector::initElementAndPseudoState): Eliminated code to set
+        currentEncodedURL.
+        (WebCore::checkPseudoState): Moved most of the code inside a new
+        PageGroup::isLinkVisited function.
+        (WebCore::CSSStyleSelector::canShareStyleWithElement): Tightened code a bit by using
+        references and only getting colors when needed.
+        (WebCore::CSSStyleSelector::getColorFromPrimitiveValue): Ditto.
+        * css/CSSStyleSelector.h: Removed EncodedURL, m_encodedURL, and setEncodedURL.
+
+        * dom/Document.cpp:
+        (WebCore::Document::attach): Removed call to setEncodedURL.
+        (WebCore::Document::setURL): Ditto.
+        (WebCore::Document::recalcStyleSelector): Ditto.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::addBackForwardItemClippedAtTarget): Changed code to use
+        early exit idiom to be a little more readable.
+        (WebCore::FrameLoader::urlsMatchItem): Change to use a reference for slightly
+        better efficiency.
+        (WebCore::FrameLoader::goToItem): Use early exit idiom to be a little more
+        readable.
+        (WebCore::FrameLoader::updateHistoryForStandardLoad): Moved history code back
+        in here and got rid of the helper function updateGlobalHistory, restoring the
+        logic before r30549. Also added a call to the new addVisitedLink function.
+        (WebCore::FrameLoader::updateHistoryForClientRedirect): Added code to call
+        addVisitedLink here.
+        (WebCore::FrameLoader::updateHistoryForBackForwardNavigation): Removed comment.
+        (WebCore::FrameLoader::updateHistoryForReload): Removed call to
+        updateGlobalHistory; we can just go without updating global history or
+        visited links here, at least for now, since it's not clear that a reload
+        is a "history event".
+        (WebCore::FrameLoader::updateHistoryForRedirectWithLockedHistory): Moved
+        history code back where it was, and added the call to addVisitedLink, just
+        as in updateHistoryForStandardLoad above.
+        * loader/FrameLoader.h: Removed updateGlobalHistory function.
+
+        * page/Chrome.cpp:
+        (WebCore::ChromeClient::populateVisitedLinks): Added. Empty placeholder so we
+        don't have to implement this for every port all at once.
+        (WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer): Changed to use the
+        new PageGroup class.
+        * page/ChromeClient.h: Added populateVisitedLinks function, used to fill the
+        visited links set from the global history at application startup time.
+
+        * page/FrameTree.cpp:
+        (WebCore::FrameTree::find): Updated to use the new PageGroup class.
+
+        * page/GlobalHistory.h: Removed.
+        * page/win/GlobalHistoryWin.cpp: Removed.
+        * page/mac/GlobalHistoryMac.mm: Removed.
+        * platform/mac/WebCoreHistory.h: Removed.
+        * platform/mac/WebCoreHistory.m: Removed.
+        * platform/win/WebCoreHistory.cpp: Removed.
+        * platform/win/WebCoreHistory.h: Removed.
+
+        * page/Page.cpp:
+        (WebCore::Page::Page): Set m_group to 0.
+        (WebCore::Page::setGroupName): Set up m_group. If the page is not in any
+        group, set it to 0 for now to postpone the cost of creating a group.
+        (WebCore::Page::initGroup): Added. Sets m_group to point to a single-page
+        group; used when getting a group.
+        (WebCore::Page::removeAllVisitedLinks): Added. Calls removeVisitedLinks
+        on all page groups.
+        * page/Page.h: Moved enums inside the WebCore namespace. Removed the
+        frameNamespace function and instead added the group and groupPtr functions.
+
+        * page/PageGroup.cpp: Added. Contains all the visited code from the
+        CSSStyleSelector in the isVisitedLink function, but more efficient because
+        we don't allocate memory for the buffer.
+        * page/PageGroup.h: Added.
+
+        * platform/gtk/TemporaryLinkStubs.cpp: Removed historyContains.
+        * platform/qt/TemporaryLinkStubs.cpp: Removed unneeded include.
+        * platform/wx/TemporaryLinkStubs.cpp: Removed historyContains.
+
 2008-03-06  Mark Rowe  <mrowe@apple.com>
 
         Fix 64-bit Mac build.
index ea26295..f57c758 100644 (file)
@@ -407,6 +407,7 @@ __ZN7WebCore4Page37setInLowQualityImageInterpolationModeEb
 __ZN7WebCore4Page6goBackEv
 __ZN7WebCore4Page8goToItemEPNS_11HistoryItemENS_13FrameLoadTypeE
 __ZN7WebCore4Page9goForwardEv
+__ZN7WebCore4Page9initGroupEv
 __ZN7WebCore4PageC1EPNS_12ChromeClientEPNS_17ContextMenuClientEPNS_12EditorClientEPNS_10DragClientEPNS_15InspectorClientE
 __ZN7WebCore4PageD1Ev
 __ZN7WebCore5Cache11setDisabledEb
@@ -563,6 +564,8 @@ __ZN7WebCore9HTMLNames7srcAttrE
 __ZN7WebCore9HTMLNames8hrefAttrE
 __ZN7WebCore9PageCache11setCapacityEi
 __ZN7WebCore9PageCache27releaseAutoreleasedPagesNowEv
+__ZN7WebCore9PageGroup14addVisitedLinkEPKtm
+__ZN7WebCore9PageGroup21removeAllVisitedLinksEv
 __ZN7WebCore9Selection22expandUsingGranularityENS_15TextGranularityE
 __ZN7WebCore9TimerBase4stopEv
 __ZN7WebCore9TimerBase5startEdd
index a292dfc..c96fe2a 100644 (file)
                                >\r
                        </File>\r
                        <File\r
-                               RelativePath="..\bridge\GlobalHistory.h"\r
-                               >\r
-                       </File>\r
-                       <File\r
                                RelativePath="..\page\History.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\page\PageGroup.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\page\PageGroup.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="..\page\Plugin.h"\r
                                >\r
                        </File>\r
                                        >\r
                                </File>\r
                                <File\r
-                                       RelativePath="..\page\win\GlobalHistoryWin.cpp"\r
-                                       >\r
-                               </File>\r
-                               <File\r
                                        RelativePath="..\page\win\PageWin.cpp"\r
                                        >\r
                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
-                                       RelativePath="..\platform\win\WebCoreHistory.cpp"\r
-                                       >\r
-                               </File>\r
-                               <File\r
-                                       RelativePath="..\platform\win\WebCoreHistory.h"\r
-                                       >\r
-                               </File>\r
-                               <File\r
                                        RelativePath="..\platform\win\WebCoreTextRenderer.cpp"\r
                                        >\r
                                </File>\r
index 95a432a..249203f 100644 (file)
                1AE82FED0CAB07EE002237AE /* JSSQLResultSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE82FEB0CAB07EE002237AE /* JSSQLResultSet.h */; };
                1AE830440CAB0ED1002237AE /* JSDatabaseCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AE830420CAB0ED1002237AE /* JSDatabaseCustom.cpp */; };
                1AF326460D78B5530068F0C4 /* AXObjectCacheMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AF326400D78B5530068F0C4 /* AXObjectCacheMac.mm */; };
-               1AF326470D78B5530068F0C4 /* GlobalHistoryMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AF326410D78B5530068F0C4 /* GlobalHistoryMac.mm */; };
                1AF326480D78B5530068F0C4 /* WebCoreAXObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AF326420D78B5530068F0C4 /* WebCoreAXObject.h */; };
                1AF326490D78B5530068F0C4 /* WebCoreAXObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AF326430D78B5530068F0C4 /* WebCoreAXObject.mm */; };
                1AF326780D78B9440068F0C4 /* AXObjectCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AF326760D78B9440068F0C4 /* AXObjectCache.h */; };
                1AF326790D78B9440068F0C4 /* EditorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AF326770D78B9440068F0C4 /* EditorClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               1AF3267B0D78B94E0068F0C4 /* GlobalHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AF3267A0D78B94E0068F0C4 /* GlobalHistory.h */; };
                1AFE117D0CBFFB36003017FA /* SQLResultSetRowList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFE117B0CBFFB36003017FA /* SQLResultSetRowList.cpp */; };
                1AFE117E0CBFFB36003017FA /* SQLResultSetRowList.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AFE117C0CBFFB36003017FA /* SQLResultSetRowList.h */; };
                1AFE11990CBFFCC4003017FA /* JSSQLResultSetRowList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFE11970CBFFCC4003017FA /* JSSQLResultSetRowList.cpp */; };
                85FF315A0AAFBFCB00374F38 /* DOMKeyboardEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 85FF31580AAFBFCB00374F38 /* DOMKeyboardEvent.h */; };
                85FF315B0AAFBFCB00374F38 /* DOMKeyboardEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = 85FF31590AAFBFCB00374F38 /* DOMKeyboardEvent.mm */; };
                929264770B61FC7200B41D34 /* JSDocumentCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 929264760B61FC7200B41D34 /* JSDocumentCustom.cpp */; };
+               9302B0BD0D79F82900C7EE83 /* PageGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9302B0BC0D79F82900C7EE83 /* PageGroup.cpp */; };
+               9302B0BF0D79F82C00C7EE83 /* PageGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = 9302B0BE0D79F82C00C7EE83 /* PageGroup.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9305B24D098F1B6B00C28855 /* Timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9305B24C098F1B6B00C28855 /* Timer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                930705D809E0C9B700B17FE4 /* JSCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 930705D709E0C9B700B17FE4 /* JSCounter.cpp */; };
                930705DA09E0C9BF00B17FE4 /* JSCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 930705D909E0C9BF00B17FE4 /* JSCounter.h */; };
                93F1999D08245E59001E9ABC /* DeprecatedValueList.h in Headers */ = {isa = PBXBuildFile; fileRef = F58786C202DE3B8601EA4122 /* DeprecatedValueList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93F1999E08245E59001E9ABC /* DeprecatedValueListImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = F587853B02DE375901EA4122 /* DeprecatedValueListImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93F199A808245E59001E9ABC /* WebCoreFrameView.h in Headers */ = {isa = PBXBuildFile; fileRef = F587854C02DE375901EA4122 /* WebCoreFrameView.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               93F199A908245E59001E9ABC /* WebCoreHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = F5517DC2031AB56301A80180 /* WebCoreHistory.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93F199B308245E59001E9ABC /* WebCoreViewFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = F587855402DE375901EA4122 /* WebCoreViewFactory.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93F199B808245E59001E9ABC /* ScrollBar.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7B2AF80450824100A8000F /* ScrollBar.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93F199BB08245E59001E9ABC /* WebCoreKeyboardUIMode.h in Headers */ = {isa = PBXBuildFile; fileRef = BE983D95052A2E0A00892D85 /* WebCoreKeyboardUIMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93F19A9D08245E59001E9ABC /* TextResourceDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F523D27802DE43D7018635CA /* TextResourceDecoder.cpp */; };
                93F19AB908245E59001E9ABC /* Range.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F523D30302DE4476018635CA /* Range.cpp */; };
                93F19ABC08245E59001E9ABC /* XMLTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F523D30902DE4476018635CA /* XMLTokenizer.cpp */; };
-               93F19AC808245E59001E9ABC /* WebCoreHistory.m in Sources */ = {isa = PBXBuildFile; fileRef = F5517DC3031AB56301A80180 /* WebCoreHistory.m */; };
                93F19AD508245E59001E9ABC /* RenderTreeAsText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93955A4203D72932008635CE /* RenderTreeAsText.cpp */; };
                93F19ADC08245E59001E9ABC /* PlatformScrollBarMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC7B2AF90450824100A8000F /* PlatformScrollBarMac.mm */; };
                93F19AE108245E59001E9ABC /* BlockExceptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 65F80697054D9F86008BF776 /* BlockExceptions.mm */; };
                1AE82FEB0CAB07EE002237AE /* JSSQLResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLResultSet.h; sourceTree = "<group>"; };
                1AE830420CAB0ED1002237AE /* JSDatabaseCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDatabaseCustom.cpp; sourceTree = "<group>"; };
                1AF326400D78B5530068F0C4 /* AXObjectCacheMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AXObjectCacheMac.mm; sourceTree = "<group>"; };
-               1AF326410D78B5530068F0C4 /* GlobalHistoryMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GlobalHistoryMac.mm; sourceTree = "<group>"; };
                1AF326420D78B5530068F0C4 /* WebCoreAXObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreAXObject.h; sourceTree = "<group>"; };
                1AF326430D78B5530068F0C4 /* WebCoreAXObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreAXObject.mm; sourceTree = "<group>"; };
                1AF326760D78B9440068F0C4 /* AXObjectCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AXObjectCache.h; sourceTree = "<group>"; };
                1AF326770D78B9440068F0C4 /* EditorClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditorClient.h; sourceTree = "<group>"; };
-               1AF3267A0D78B94E0068F0C4 /* GlobalHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlobalHistory.h; sourceTree = "<group>"; };
                1AFE117B0CBFFB36003017FA /* SQLResultSetRowList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLResultSetRowList.cpp; sourceTree = "<group>"; };
                1AFE117C0CBFFB36003017FA /* SQLResultSetRowList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLResultSetRowList.h; sourceTree = "<group>"; };
                1AFE118C0CBFFC4E003017FA /* SQLResultSetRowList.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SQLResultSetRowList.idl; sourceTree = "<group>"; };
                85FF31580AAFBFCB00374F38 /* DOMKeyboardEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOMKeyboardEvent.h; sourceTree = "<group>"; };
                85FF31590AAFBFCB00374F38 /* DOMKeyboardEvent.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMKeyboardEvent.mm; sourceTree = "<group>"; };
                929264760B61FC7200B41D34 /* JSDocumentCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSDocumentCustom.cpp; sourceTree = "<group>"; };
+               9302B0BC0D79F82900C7EE83 /* PageGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageGroup.cpp; sourceTree = "<group>"; };
+               9302B0BE0D79F82C00C7EE83 /* PageGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageGroup.h; sourceTree = "<group>"; };
                9305B24C098F1B6B00C28855 /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Timer.h; sourceTree = "<group>"; };
                9307059009E0C75800B17FE4 /* CSSPrimitiveValue.idl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; path = CSSPrimitiveValue.idl; sourceTree = "<group>"; };
                930705C709E0C95F00B17FE4 /* Counter.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Counter.idl; sourceTree = "<group>"; };
                F523D30402DE4476018635CA /* Range.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Range.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F523D30902DE4476018635CA /* XMLTokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XMLTokenizer.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F523D30A02DE4476018635CA /* XMLTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = XMLTokenizer.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
-               F5517DC2031AB56301A80180 /* WebCoreHistory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCoreHistory.h; sourceTree = "<group>"; };
-               F5517DC3031AB56301A80180 /* WebCoreHistory.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = WebCoreHistory.m; sourceTree = "<group>"; };
                F58784F002DE375901EA4122 /* CursorMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CursorMac.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F587851502DE375901EA4122 /* DeprecatedPtrListImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = DeprecatedPtrListImpl.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F587851602DE375901EA4122 /* DeprecatedPtrListImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeprecatedPtrListImpl.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                                84B2B24F056BF15F00D2B771 /* SSLKeyGeneratorMac.mm */,
                                6582A15509999D6D00BEEB6D /* SystemTimeMac.cpp */,
                                51DF6D7F0B92A18E00C2DC85 /* ThreadCheck.mm */,
-                               F5517DC2031AB56301A80180 /* WebCoreHistory.h */,
-                               F5517DC3031AB56301A80180 /* WebCoreHistory.m */,
                                84B2B1F7056BEF3A00D2B771 /* WebCoreKeyGenerator.h */,
                                84B2B1F8056BEF3A00D2B771 /* WebCoreKeyGenerator.m */,
                                934D9BA60B8C1175007B42A9 /* WebCoreNSStringExtras.h */,
                                65A21483097A3F5300B9050A /* FrameTree.h */,
                                65CBFEF70974F607001DAC25 /* FrameView.cpp */,
                                65CBFEF80974F607001DAC25 /* FrameView.h */,
-                               1AF3267A0D78B94E0068F0C4 /* GlobalHistory.h */,
                                BC94D1500C275C8B006BC617 /* History.cpp */,
                                BC94D1510C275C8B006BC617 /* History.h */,
                                BC94D1520C275C8B006BC617 /* History.idl */,
                                935C476209AC4CE600A6AAB4 /* MouseEventWithHitTestResults.h */,
                                65FEA86809833ADE00BED4AB /* Page.cpp */,
                                65A21467097A329100B9050A /* Page.h */,
+                               9302B0BC0D79F82900C7EE83 /* PageGroup.cpp */,
+                               9302B0BE0D79F82C00C7EE83 /* PageGroup.h */,
                                65D1C1C909932B22000CB324 /* Plugin.h */,
                                BCEC01BA0C274DAC009F4EC9 /* Screen.cpp */,
                                BCEC01BB0C274DAC009F4EC9 /* Screen.h */,
                        isa = PBXGroup;
                        children = (
                                1AF326400D78B5530068F0C4 /* AXObjectCacheMac.mm */,
-                               1AF326410D78B5530068F0C4 /* GlobalHistoryMac.mm */,
                                1AF326420D78B5530068F0C4 /* WebCoreAXObject.h */,
                                1AF326430D78B5530068F0C4 /* WebCoreAXObject.mm */,
                                ABAF22070C03B1C700B0BCF0 /* ChromeMac.mm */,
                                B255996F0D00D8BA00BB825C /* WKTableTransferFilter.h in Headers */,
                                654EC611097778F500DAB52C /* WebCoreFrameBridge.h in Headers */,
                                93F199A808245E59001E9ABC /* WebCoreFrameView.h in Headers */,
-                               93F199A908245E59001E9ABC /* WebCoreHistory.h in Headers */,
                                93F199C208245E59001E9ABC /* WebCoreKeyGenerator.h in Headers */,
                                93F199BB08245E59001E9ABC /* WebCoreKeyboardUIMode.h in Headers */,
                                934D9BA70B8C1175007B42A9 /* WebCoreNSStringExtras.h in Headers */,
                                1CEFC9B90D78DC8C007D2579 /* SchedulePair.h in Headers */,
                                1AF326480D78B5530068F0C4 /* WebCoreAXObject.h in Headers */,
                                1AF326780D78B9440068F0C4 /* AXObjectCache.h in Headers */,
-                               1AF3267B0D78B94E0068F0C4 /* GlobalHistory.h in Headers */,
+                               9302B0BF0D79F82C00C7EE83 /* PageGroup.h in Headers */,
                                BCA83E500D7CE1E9003421A8 /* JSClipboard.h in Headers */,
                                BC6C49F40D7DBA0500FFA558 /* JSImageConstructor.h in Headers */,
                                BC3452440D7E00EA0016574A /* JSRGBColor.h in Headers */,
                                B255996D0D00D8BA00BB825C /* WKSpotLightFilter.m in Sources */,
                                B25599700D00D8BA00BB825C /* WKTableTransferFilter.m in Sources */,
                                654EC612097778F500DAB52C /* WebCoreFrameBridge.mm in Sources */,
-                               93F19AC808245E59001E9ABC /* WebCoreHistory.m in Sources */,
                                93F19AE508245E59001E9ABC /* WebCoreKeyGenerator.m in Sources */,
                                934D9BA50B8C116B007B42A9 /* WebCoreNSStringExtras.mm in Sources */,
                                DD05FE0E0B8BA3C6009ACDFE /* WebCoreObjCExtras.c in Sources */,
                                A766F3530D6BDE3500ABDDB3 /* JSCanvasPixelArrayCustom.cpp in Sources */,
                                1CEFC9BA0D78DC8C007D2579 /* SchedulePair.cpp in Sources */,
                                1AF326460D78B5530068F0C4 /* AXObjectCacheMac.mm in Sources */,
-                               1AF326470D78B5530068F0C4 /* GlobalHistoryMac.mm in Sources */,
                                1AF326490D78B5530068F0C4 /* WebCoreAXObject.mm in Sources */,
+                               9302B0BD0D79F82900C7EE83 /* PageGroup.cpp in Sources */,
                                1CE24F970D7CAF0E007E04C2 /* SchedulePairMac.mm in Sources */,
                                BCA83E4F0D7CE1E9003421A8 /* JSClipboard.cpp in Sources */,
                                BCA83E520D7CE205003421A8 /* JSClipboardCustom.cpp in Sources */,
index 8f7e2ca..bf4fee3 100644 (file)
 #include "FontValue.h"
 #include "Frame.h"
 #include "FrameView.h"
-#include "GlobalHistory.h"
 #include "HTMLDocument.h"
 #include "HTMLElement.h"
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
 #include "MediaList.h"
 #include "MediaQueryEvaluator.h"
+#include "Page.h"
+#include "PageGroup.h"
 #include "Pair.h"
 #include "Rect.h"
 #include "RenderTheme.h"
@@ -228,7 +229,6 @@ CSSStyleSheet* CSSStyleSelector::m_viewSourceSheet = 0;
 CSSStyleSheet *CSSStyleSelector::m_svgSheet = 0;
 #endif
 
-static CSSStyleSelector::EncodedURL* currentEncodedURL = 0;
 static PseudoState pseudoState;
 
 static const MediaQueryEvaluator& screenEval()
@@ -312,28 +312,10 @@ void CSSStyleSelector::init()
     m_medium = 0;
 }
 
-void CSSStyleSelector::setEncodedURL(const KURL& url)
-{
-    KURL u = url;
-
-    u.setQuery(String());
-    u.setRef(String());
-    m_encodedURL.file = u.string();
-    int pos = m_encodedURL.file.reverseFind('/');
-    m_encodedURL.path = m_encodedURL.file;
-    if (pos > 0) {
-        m_encodedURL.path.truncate(pos);
-        m_encodedURL.path.append('/');
-    }
-    u.setPath(String());
-    m_encodedURL.prefix = u.string();
-}
-
 CSSStyleSelector::~CSSStyleSelector()
 {
     delete m_medium;
-    ::delete m_rootDefaultStyle;
-
+    delete m_rootDefaultStyle;
     delete m_authorStyle;
     delete m_userStyle;
 }
@@ -533,7 +515,6 @@ void CSSStyleSelector::initElementAndPseudoState(Element* e)
         m_styledElement = static_cast<StyledElement*>(m_element);
     else
         m_styledElement = 0;
-    currentEncodedURL = &m_encodedURL;
     pseudoState = PseudoUnknown;
 }
 
@@ -564,81 +545,7 @@ void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParen
     m_fontDirty = false;
 }
 
-static inline int findSlashDotDotSlash(const UChar* characters, size_t length)
-{
-    unsigned loopLimit = length < 4 ? 0 : length - 3;
-    for (unsigned i = 0; i < loopLimit; ++i) {
-        if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '.' && characters[i + 3] == '/')
-            return i;
-    }
-    return -1;
-}
-
-static inline int findSlashSlash(const UChar* characters, size_t length, int position)
-{
-    unsigned loopLimit = length < 2 ? 0 : length - 1;
-    for (unsigned i = position; i < loopLimit; ++i) {
-        if (characters[i] == '/' && characters[i + 1] == '/')
-            return i;
-    }
-    return -1;
-}
-
-static inline int findSlashDotSlash(const UChar* characters, size_t length)
-{
-    unsigned loopLimit = length < 3 ? 0 : length - 2;
-    for (unsigned i = 0; i < loopLimit; ++i) {
-        if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '/')
-            return i;
-    }
-    return -1;
-}
-
-static inline bool containsColonSlashSlash(const UChar* characters, unsigned length)
-{
-    unsigned loopLimit = length < 3 ? 0 : length - 2;
-    for (unsigned i = 0; i < loopLimit; ++i)
-        if (characters[i] == ':' && characters[i + 1] == '/' && characters[i + 2] == '/')
-            return true;
-    return false;
-}
-
-static void cleanPath(Vector<UChar, 512>& path)
-{
-    int pos;
-    while ((pos = findSlashDotDotSlash(path.data(), path.size())) != -1) {
-        int prev = reverseFind(path.data(), path.size(), '/', pos - 1);
-        // don't remove the host, i.e. http://foo.org/../foo.html
-        if (prev < 0 || (prev > 3 && path[prev - 2] == ':' && path[prev - 1] == '/'))
-            path.remove(pos, 3);
-        else
-            path.remove(prev, pos - prev + 3);
-    }
-
-    // Don't remove "//" from an anchor identifier. -rjw
-    // Set refPos to -2 to mean "I haven't looked for the anchor yet".
-    // We don't want to waste a function call on the search for the the anchor
-    // in the vast majority of cases where there is no "//" in the path.
-    pos = 0;
-    int refPos = -2;
-    while ((pos = findSlashSlash(path.data(), path.size(), pos)) != -1) {
-        if (refPos == -2)
-            refPos = find(path.data(), path.size(), '#');
-        if (refPos > 0 && pos >= refPos)
-            break;
-
-        if (pos == 0 || path[pos - 1] != ':')
-            path.remove(pos);
-        else
-            pos += 2;
-    }
-
-    // FIXME: We don't want to remove "/./" from an anchor identifier either.
-    while ((pos = findSlashDotSlash(path.data(), path.size())) != -1)
-        path.remove(pos, 2);
-}
-
-static void checkPseudoState(Element *e, bool checkVisited = true)
+static void checkPseudoState(Element* e, bool checkVisited = true)
 {
     if (!e->isLink()) {
         pseudoState = PseudoNone;
@@ -667,26 +574,21 @@ static void checkPseudoState(Element *e, bool checkVisited = true)
         return;
     }
 
-    const UChar* characters = attr->characters();
-    unsigned length = attr->length();
+    Document* document = e->document();
 
-    if (containsColonSlashSlash(characters, length)) {
-        // FIXME: Strange to not clean the path just beacause it has "://" in it.
-        pseudoState = historyContains(characters, length) ? PseudoVisited : PseudoLink;
+    Frame* frame = document->frame();
+    if (!frame) {
+        pseudoState = PseudoLink;
         return;
     }
 
-    Vector<UChar, 512> buffer;
-    if (length && characters[0] == '/') {
-        buffer.append(currentEncodedURL->prefix.characters(), currentEncodedURL->prefix.length());
-    } else if (length && characters[0] == '#') {
-        buffer.append(currentEncodedURL->file.characters(), currentEncodedURL->file.length());
-    } else {
-        buffer.append(currentEncodedURL->path.characters(), currentEncodedURL->path.length());
+    Page* page = frame->page();
+    if (!page) {
+        pseudoState = PseudoLink;
+        return;
     }
-    buffer.append(characters, length);
-    cleanPath(buffer);
-    pseudoState = historyContains(buffer.data(), buffer.size()) ? PseudoVisited : PseudoLink;
+
+    pseudoState = page->group().isLinkVisited(document, *attr) ? PseudoVisited : PseudoLink;
 }
 
 // a helper function for parsing nth-arguments
@@ -825,12 +727,14 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n)
                     mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(m_styledElement->mappedAttributes());
                 if (mappedAttrsMatch) {
                     bool linksMatch = true;
+
                     if (s->isLink()) {
                         // We need to check to see if the visited state matches.
-                        Color linkColor = m_element->document()->linkColor();
-                        Color visitedColor = m_element->document()->visitedLinkColor();
-                        if (pseudoState == PseudoUnknown)
+                        if (pseudoState == PseudoUnknown) {
+                            const Color& linkColor = m_element->document()->linkColor();
+                            const Color& visitedColor = m_element->document()->visitedLinkColor();
                             checkPseudoState(m_element, style->pseudoState() != PseudoAnyLink || linkColor != visitedColor);
+                        }
                         linksMatch = (pseudoState == style->pseudoState());
                     }
                     
@@ -5130,8 +5034,8 @@ Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveV
         if (ident == CSS_VAL__WEBKIT_TEXT)
             col = m_element->document()->textColor();
         else if (ident == CSS_VAL__WEBKIT_LINK) {
-            Color linkColor = m_element->document()->linkColor();
-            Color visitedColor = m_element->document()->visitedLinkColor();
+            const Color& linkColor = m_element->document()->linkColor();
+            const Color& visitedColor = m_element->document()->visitedLinkColor();
             if (linkColor == visitedColor)
                 col = linkColor;
             else {
index b5ba49b..7e3cc52 100644 (file)
@@ -110,14 +110,6 @@ public:
 
         bool strictParsing;
 
-        struct EncodedURL {
-            String prefix; // protocol, host, etc.
-            String path;
-            String file;
-        } m_encodedURL;
-
-        void setEncodedURL(const KURL& url);
-
         // Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return
         // the correct font size scaled relative to the user's default (medium).
         float fontSizeForKeyword(int keyword, bool quirksMode, bool monospace) const;
@@ -250,11 +242,8 @@ public:
         bool m_matchAuthorAndUserStyles;
 
         RefPtr<CSSFontSelector> m_fontSelector;
-
         HashSet<AtomicStringImpl*> m_selectorAttrs;
-        
         Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls;
-        
         Vector<MediaQueryResult*> m_viewportDependentMediaQueryResults;
 
         void applyProperty(int id, CSSValue*);
index f6de5de..47a6fd2 100644 (file)
@@ -1215,7 +1215,6 @@ void Document::attach()
         if (Settings* docSettings = settings())
             matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled();
         m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles);
-        m_styleSelector->setEncodedURL(m_url);
     }
 
     recalcStyle(Force);
@@ -1636,9 +1635,6 @@ void Document::setURL(const KURL& url)
         return;
 
     m_url = url;
-    if (m_styleSelector)
-        m_styleSelector->setEncodedURL(url);
-
     m_isAllowedToLoadLocalResources = shouldBeAllowedToLoadLocalResources();
  }
  
@@ -2208,7 +2204,6 @@ void Document::recalcStyleSelector()
     // Create a new style selector
     delete m_styleSelector;
     m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles);
-    m_styleSelector->setEncodedURL(m_url);
     m_didCalculateStyleSelector = true;
 }
 
index 7f1949c..931f705 100644 (file)
@@ -66,6 +66,7 @@
 #include "MainResourceLoader.h"
 #include "Page.h"
 #include "PageCache.h"
+#include "PageGroup.h"
 #include "PluginInfoStore.h"
 #include "ProgressTracker.h"
 #include "RenderPart.h"
@@ -3848,21 +3849,25 @@ PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal)
 
 void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip)
 {
-    if (Page* page = m_frame->page())
-        if (!documentLoader()->urlForHistory().isEmpty()) {
-            Frame* mainFrame = page->mainFrame();
-            ASSERT(mainFrame);
-            FrameLoader* frameLoader = mainFrame->loader();
-
-            if (!frameLoader->m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) {
-                frameLoader->m_didPerformFirstNavigation = true;
-                m_client->didPerformFirstNavigation();
-            }
+    Page* page = m_frame->page();
+    if (!page)
+        return;
 
-            RefPtr<HistoryItem> item = frameLoader->createHistoryItemTree(m_frame, doClip);
-            LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->url().string().ascii().data());
-            page->backForwardList()->addItem(item);
-        }
+    if (documentLoader()->urlForHistory().isEmpty())
+        return;
+
+    Frame* mainFrame = page->mainFrame();
+    ASSERT(mainFrame);
+    FrameLoader* frameLoader = mainFrame->loader();
+
+    if (!frameLoader->m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) {
+        frameLoader->m_didPerformFirstNavigation = true;
+        m_client->didPerformFirstNavigation();
+    }
+
+    RefPtr<HistoryItem> item = frameLoader->createHistoryItemTree(m_frame, doClip);
+    LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->url().string().ascii().data());
+    page->backForwardList()->addItem(item);
 }
 
 PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget)
@@ -4110,13 +4115,12 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
 // Walk the frame tree and ensure that the URLs match the URLs in the item.
 bool FrameLoader::urlsMatchItem(HistoryItem* item) const
 {
-    KURL currentURL = documentLoader()->url();
-    
+    const KURL& currentURL = documentLoader()->url();
     if (!equalIgnoringRef(currentURL, item->url()))
         return false;
-    
+
     const HistoryItemVector& childItems = item->children();
-    
+
     unsigned size = childItems.size();
     for (unsigned i = 0; i < size; ++i) {
         Frame* childFrame = m_frame->tree()->child(childItems[i]->target());
@@ -4137,17 +4141,19 @@ void FrameLoader::goToItem(HistoryItem* targetItem, FrameLoadType type)
     // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls
     // Ultimately, history item navigations should go through the policy delegate. That's covered in:
     // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate
-    if (Page* page = m_frame->page())
-        if (m_client->shouldGoToHistoryItem(targetItem)) {
-            BackForwardList* bfList = page->backForwardList();
-            HistoryItem* currentItem = bfList->currentItem();
-            
-            // Set the BF cursor before commit, which lets the user quickly click back/forward again.
-            // - plus, it only makes sense for the top level of the operation through the frametree,
-            // as opposed to happening for some/one of the page commits that might happen soon
-            bfList->goToItem(targetItem);
-            recursiveGoToItem(targetItem, currentItem, type);
-        }
+    Page* page = m_frame->page();
+    if (!page)
+        return;
+    if (!m_client->shouldGoToHistoryItem(targetItem))
+        return;
+
+    // Set the BF cursor before commit, which lets the user quickly click back/forward again.
+    // - plus, it only makes sense for the top level of the operation through the frametree,
+    // as opposed to happening for some/one of the page commits that might happen soon
+    BackForwardList* bfList = page->backForwardList();
+    HistoryItem* currentItem = bfList->currentItem();    
+    bfList->goToItem(targetItem);
+    recursiveGoToItem(targetItem, currentItem, type);
 }
 
 // The general idea here is to traverse the frame tree and the item tree in parallel,
@@ -4225,25 +4231,23 @@ bool FrameLoader::childFramesMatchItem(HistoryItem* item) const
     return true;
 }
 
-void FrameLoader::updateGlobalHistory()
-{
-    Settings* settings = m_frame->settings();
-    if (!settings)
-        return;
-    if (settings->privateBrowsingEnabled())
-        return;
-    const KURL& url = documentLoader()->urlForHistory();
-    if (url.isEmpty())
-        return;
-    m_client->updateGlobalHistory(url);
-}
+// There are 3 things you might think of as "history", all of which are handled by these functions.
+//
+//     1) Back/forward: The m_currentHistoryItem is part of this mechanism.
+//     2) Global history: Handled by the client.
+//     3) Visited links: Handled by the PageGroup.
 
 void FrameLoader::updateHistoryForStandardLoad()
 {
     LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", documentLoader()->url().string().ascii().data());
-    
+
+    Settings* settings = m_frame->settings();
+    bool needPrivacy = !settings || settings->privateBrowsingEnabled();
+    const KURL& historyURL = documentLoader()->urlForHistory();
+
     // If the navigation occured during load and this is a subframe, update the current
-    // history item rather than adding a new one. <rdar://problem/5333496>
+    // back/forward item rather than adding a new one and don't add the new URL to global
+    // history at all. But do add it to visited links. <rdar://problem/5333496>
     bool frameNavigationDuringLoad = false;
     if (m_navigationDuringLoad) {
         HTMLFrameOwnerElement* owner = m_frame->ownerElement();
@@ -4252,14 +4256,20 @@ void FrameLoader::updateHistoryForStandardLoad()
     }
 
     if (!frameNavigationDuringLoad && !documentLoader()->isClientRedirect()) {
-        if (!documentLoader()->urlForHistory().isEmpty())
+        if (!historyURL.isEmpty()) {
             addBackForwardItemClippedAtTarget(true);
+            if (!needPrivacy)
+                m_client->updateGlobalHistory(historyURL);
+        }
     } else if (documentLoader()->unreachableURL().isEmpty() && m_currentHistoryItem) {
         m_currentHistoryItem->setURL(documentLoader()->url());
         m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request());
     }
 
-    updateGlobalHistory();
+    if (!historyURL.isEmpty() && !needPrivacy) {
+        if (Page* page = m_frame->page())
+            page->group().addVisitedLink(historyURL);
+    }
 }
 
 void FrameLoader::updateHistoryForClientRedirect()
@@ -4276,7 +4286,14 @@ void FrameLoader::updateHistoryForClientRedirect()
         m_currentHistoryItem->clearScrollPoint();
     }
 
-    // FIXME: Should we call updateGlobalHistory here?
+    Settings* settings = m_frame->settings();
+    bool needPrivacy = !settings || settings->privateBrowsingEnabled();
+    const KURL& historyURL = documentLoader()->urlForHistory();
+
+    if (!historyURL.isEmpty() && !needPrivacy) {
+        if (Page* page = m_frame->page())
+            page->group().addVisitedLink(historyURL);
+    }
 }
 
 void FrameLoader::updateHistoryForBackForwardNavigation()
@@ -4288,8 +4305,6 @@ void FrameLoader::updateHistoryForBackForwardNavigation()
 
     // Must grab the current scroll position before disturbing it
     saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get());
-
-    // FIXME: Should we call updateGlobalHistory here?
 }
 
 void FrameLoader::updateHistoryForReload()
@@ -4309,8 +4324,6 @@ void FrameLoader::updateHistoryForReload()
         if (documentLoader()->unreachableURL().isEmpty())
             m_currentHistoryItem->setURL(documentLoader()->requestURL());
     }
-    
-    updateGlobalHistory();
 }
 
 void FrameLoader::updateHistoryForRedirectWithLockedHistory()
@@ -4320,9 +4333,16 @@ void FrameLoader::updateHistoryForRedirectWithLockedHistory()
         LOG(History, "WebCoreHistory: Updating History for internal load in frame %s", documentLoader()->title().utf8().data());
 #endif
     
+    Settings* settings = m_frame->settings();
+    bool needPrivacy = !settings || settings->privateBrowsingEnabled();
+    const KURL& historyURL = documentLoader()->urlForHistory();
+
     if (documentLoader()->isClientRedirect()) {
-        if (!m_currentHistoryItem && !m_frame->tree()->parent())
+        if (!m_currentHistoryItem && !m_frame->tree()->parent()) {
             addBackForwardItemClippedAtTarget(true);
+            if (!needPrivacy && !historyURL.isEmpty())
+                m_client->updateGlobalHistory(historyURL);
+        }
         if (m_currentHistoryItem) {
             m_currentHistoryItem->setURL(documentLoader()->url());
             m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request());
@@ -4333,7 +4353,10 @@ void FrameLoader::updateHistoryForRedirectWithLockedHistory()
             parentFrame->loader()->m_currentHistoryItem->addChildItem(createHistoryItem(true));
     }
 
-    updateGlobalHistory();
+    if (!historyURL.isEmpty() && !needPrivacy) {
+        if (Page* page = m_frame->page())
+            page->group().addVisitedLink(historyURL);
+    }
 }
 
 void FrameLoader::updateHistoryForCommit()
index 182f1c3..6a9e688 100644 (file)
@@ -456,8 +456,6 @@ namespace WebCore {
         void updateHistoryForClientRedirect();
         void updateHistoryForCommit();
     
-        void updateGlobalHistory();
-
         void redirectionTimerFired(Timer<FrameLoader>*);
         void checkCompletedTimerFired(Timer<FrameLoader>*);
         void checkLoadCompleteTimerFired(Timer<FrameLoader>*);
index 221a03b..d9b03a6 100644 (file)
@@ -33,6 +33,7 @@
 #include "InspectorController.h"
 #include "JSDOMWindow.h"
 #include "Page.h"
+#include "PageGroup.h"
 #include "PausedTimeouts.h"
 #include "ResourceHandle.h"
 #include "SecurityOrigin.h"
@@ -349,17 +350,18 @@ void ChromeClient::dashboardRegionsChanged()
 {
 }
 
+void ChromeClient::populateVisitedLinks()
+{
+}
+
 // --------
 
 PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf)
 {
-    const HashSet<Page*>* group = page->frameNamespace();
-
-    if (!group)
-        return;
+    const HashSet<Page*>& pages = page->group().pages();
 
-    HashSet<Page*>::const_iterator end = group->end();
-    for (HashSet<Page*>::const_iterator it = group->begin(); it != end; ++it) {
+    HashSet<Page*>::const_iterator end = pages.end();
+    for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) {
         Page* otherPage = *it;
         if ((deferSelf || otherPage != page)) {
             if (!otherPage->defersLoading())
index 30ba099..ec76c24 100644 (file)
@@ -121,6 +121,8 @@ namespace WebCore {
 
         virtual void dashboardRegionsChanged();
 
+        virtual void populateVisitedLinks();
+
     protected:
         virtual ~ChromeClient() { }
     };
index 0831be8..d903b49 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "Frame.h"
 #include "Page.h"
+#include "PageGroup.h"
 #include <stdarg.h>
 #include <wtf/Platform.h>
 #include <wtf/StringExtras.h>
@@ -182,16 +183,17 @@ Frame* FrameTree::find(const AtomicString& name) const
         if (frame->tree()->name() == name)
             return frame;
 
-    // Search the entire tree for all other pages in this namespace.
-    const HashSet<Page*>* pages = page->frameNamespace();
-    if (pages) {
-        HashSet<Page*>::const_iterator end = pages->end();
-        for (HashSet<Page*>::const_iterator it = pages->begin(); it != end; ++it) {
-            Page* otherPage = *it;
-            if (otherPage != page)
-                for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext())
-                    if (frame->tree()->name() == name)
-                        return frame;
+    // Search the entire tree of each of the other pages in this namespace.
+    // FIXME: Is random order OK?
+    const HashSet<Page*>& pages = page->group().pages();
+    HashSet<Page*>::const_iterator end = pages.end();
+    for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) {
+        Page* otherPage = *it;
+        if (otherPage != page) {
+            for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+                if (frame->tree()->name() == name)
+                    return frame;
+            }
         }
     }
 
index bee0f02..294e349 100644 (file)
@@ -35,6 +35,7 @@
 #include "HistoryItem.h"
 #include "InspectorController.h"
 #include "Logging.h"
+#include "PageGroup.h"
 #include "ProgressTracker.h"
 #include "RenderWidget.h"
 #include "SelectionController.h"
 
 namespace WebCore {
 
+typedef HashMap<String, PageGroup*> PageGroupMap;
+
 static HashSet<Page*>* allPages;
-static HashMap<String, HashSet<Page*>*>* frameNamespaces;
+static PageGroupMap* pageGroups;
 
 #ifndef NDEBUG
 WTFLogChannel LogWebCorePageLeaks =  { 0x00000000, "", WTFLogChannelOn };
@@ -85,6 +88,7 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi
     , m_parentInspectorController(0)
     , m_didLoadUserStyleSheet(false)
     , m_userStyleSheetModificationTime(0)
+    , m_group(0)
     , m_debugger(0)
 {
     if (!allPages) {
@@ -165,37 +169,41 @@ void Page::goToItem(HistoryItem* item, FrameLoadType type)
 
 void Page::setGroupName(const String& name)
 {
-    if (frameNamespaces && !m_groupName.isEmpty()) {
-        HashSet<Page*>* oldNamespace = frameNamespaces->get(m_groupName);
-        if (oldNamespace) {
-            oldNamespace->remove(this);
-            if (oldNamespace->isEmpty()) {
-                frameNamespaces->remove(m_groupName);
-                delete oldNamespace;
-            }
-        }
+    if (!m_groupName.isEmpty()) {
+        ASSERT(!m_singlePageGroup);
+        ASSERT(m_group);
+        ASSERT(pageGroups);
+        ASSERT(pageGroups->get(m_groupName) == m_group);
+        m_group->removePage(this);
+        if (m_group->pages().isEmpty())
+            pageGroups->remove(m_groupName);
     }
     m_groupName = name;
-    if (!name.isEmpty()) {
-        if (!frameNamespaces)
-            frameNamespaces = new HashMap<String, HashSet<Page*>*>;
-        HashSet<Page*>* newNamespace = frameNamespaces->get(name);
-        if (!newNamespace) {
-            newNamespace = new HashSet<Page*>;
-            frameNamespaces->add(name, newNamespace);
+    if (name.isEmpty())
+        m_group = 0;
+    else {
+        m_singlePageGroup.clear();
+        if (!pageGroups)
+            pageGroups = new PageGroupMap;
+        pair<PageGroupMap::iterator, bool> result = pageGroups->add(name, 0);
+        if (!result.second) {
+            ASSERT(result.first->second);
+            m_group = result.first->second;
+            m_group->addPage(this);
+        } else {
+            ASSERT(!result.first->second);
+            m_group = new PageGroup(this);
+            result.first->second = m_group;
         }
-        newNamespace->add(this);
     }
 }
 
-const HashSet<Page*>* Page::frameNamespace() const
-{
-    return (frameNamespaces && !m_groupName.isEmpty()) ? frameNamespaces->get(m_groupName) : 0;
-}
-
-const HashSet<Page*>* Page::frameNamespace(const String& groupName)
+void Page::initGroup()
 {
-    return (frameNamespaces && !groupName.isEmpty()) ? frameNamespaces->get(groupName) : 0;
+    ASSERT(!m_singlePageGroup);
+    ASSERT(!m_group);
+    m_singlePageGroup.set(new PageGroup(this));
+    m_group = m_singlePageGroup.get();
 }
 
 void Page::setNeedsReapplyStyles()
@@ -360,6 +368,21 @@ const String& Page::userStyleSheet() const
     return m_userStyleSheet;
 }
 
+void Page::removeAllVisitedLinks()
+{
+    if (!allPages)
+        return;
+    HashSet<PageGroup*> groups;
+    HashSet<Page*>::iterator pagesEnd = allPages->end();
+    for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
+        if (PageGroup* group = (*it)->groupPtr())
+            groups.add(group);
+    }
+    HashSet<PageGroup*>::iterator groupsEnd = groups.end();
+    for (HashSet<PageGroup*>::iterator it = groups.begin(); it != groupsEnd; ++it)
+        (*it)->removeVisitedLinks();
+}
+
 void Page::setDebuggerForAllPages(KJS::Debugger* debugger)
 {
     ASSERT(allPages);
index d3363ad..fd5dce5 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: c++; c-basic-offset: 4 -*-
 /*
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -40,22 +40,13 @@ namespace KJS {
     class Debugger;
 }
 
-typedef enum TextCaseSensitivity {
-    TextCaseSensitive,
-    TextCaseInsensitive
-};
-
-typedef enum FindDirection {
-    FindDirectionForward,
-    FindDirectionBackward
-};
-
 namespace WebCore {
 
     class Chrome;
     class ChromeClient;
     class ContextMenuClient;
     class ContextMenuController;
+    class Document;
     class DragClient;
     class DragController;
     class EditorClient;
@@ -64,15 +55,19 @@ namespace WebCore {
     class InspectorClient;
     class InspectorController;
     class Node;
+    class PageGroup;
     class ProgressTracker;
     class Selection;
     class SelectionController;
     class Settings;
+    class KURL;
+
+    enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
+    enum FindDirection { FindDirectionForward, FindDirectionBackward };
 
     class Page : Noncopyable {
     public:
         static void setNeedsReapplyStyles();
-        static const HashSet<Page*>* frameNamespace(const String&);
 
         Page(ChromeClient*, ContextMenuClient*, EditorClient*, DragClient*, InspectorClient*);
         ~Page();
@@ -93,9 +88,10 @@ namespace WebCore {
         void goToItem(HistoryItem*, FrameLoadType);
         
         void setGroupName(const String&);
-        String groupName() const { return m_groupName; }
+        const String& groupName() const { return m_groupName; }
 
-        const HashSet<Page*>* frameNamespace() const;
+        PageGroup& group() { if (!m_group) initGroup(); return *m_group; }
+        PageGroup* groupPtr() { return m_group; } // can return 0
 
         void incrementFrameCount() { ++m_frameCount; }
         void decrementFrameCount() { --m_frameCount; }
@@ -151,7 +147,11 @@ namespace WebCore {
         static HINSTANCE instanceHandle() { return s_instanceHandle; }
 #endif
 
+        static void removeAllVisitedLinks();
+
     private:
+        void initGroup();
+
         OwnPtr<Chrome> m_chrome;
         OwnPtr<SelectionController> m_dragCaretController;
         OwnPtr<DragController> m_dragController;
@@ -182,6 +182,9 @@ namespace WebCore {
         mutable bool m_didLoadUserStyleSheet;
         mutable time_t m_userStyleSheetModificationTime;
 
+        OwnPtr<PageGroup> m_singlePageGroup;
+        PageGroup* m_group;
+
         KJS::Debugger* m_debugger;
 
 #if PLATFORM(WIN) || (PLATFORM(WX) && defined(__WXMSW__))
diff --git a/WebCore/page/PageGroup.cpp b/WebCore/page/PageGroup.cpp
new file mode 100644 (file)
index 0000000..3acc850
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "PageGroup.h"
+
+#include "ChromeClient.h"
+#include "Document.h"
+#include "Page.h"
+
+namespace WebCore {
+
+// --------
+
+PageGroup::PageGroup(Page* page)
+    : m_visitedLinksPopulated(false)
+{
+    ASSERT(page);
+    m_pages.add(page);
+}
+
+void PageGroup::addPage(Page* page)
+{
+    ASSERT(page);
+    ASSERT(!m_pages.contains(page));
+    m_pages.add(page);
+}
+
+void PageGroup::removePage(Page* page)
+{
+    ASSERT(page);
+    ASSERT(m_pages.contains(page));
+    m_pages.remove(page);
+}
+
+static inline int findSlashDotDotSlash(const UChar* characters, size_t length)
+{
+    if (length < 4)
+        return -1;
+    unsigned loopLimit = length - 3;
+    for (unsigned i = 0; i < loopLimit; ++i) {
+        if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '.' && characters[i + 3] == '/')
+            return i;
+    }
+    return -1;
+}
+
+static inline int findSlashSlash(const UChar* characters, size_t length, int position)
+{
+    if (length < 2)
+        return -1;
+    unsigned loopLimit = length - 1;
+    for (unsigned i = position; i < loopLimit; ++i) {
+        if (characters[i] == '/' && characters[i + 1] == '/')
+            return i;
+    }
+    return -1;
+}
+
+static inline int findSlashDotSlash(const UChar* characters, size_t length)
+{
+    if (length < 3)
+        return -1;
+    unsigned loopLimit = length - 2;
+    for (unsigned i = 0; i < loopLimit; ++i) {
+        if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '/')
+            return i;
+    }
+    return -1;
+}
+
+static inline bool containsColonSlashSlash(const UChar* characters, unsigned length)
+{
+    if (length < 3)
+        return false;
+    unsigned loopLimit = length - 2;
+    for (unsigned i = 0; i < loopLimit; ++i) {
+        if (characters[i] == ':' && characters[i + 1] == '/' && characters[i + 2] == '/')
+            return true;
+    }
+    return false;
+}
+
+static inline void cleanPath(Vector<UChar, 512>& path)
+{
+    // FIXME: Shold not do this in the query or anchor part.
+    int pos;
+    while ((pos = findSlashDotDotSlash(path.data(), path.size())) != -1) {
+        int prev = reverseFind(path.data(), path.size(), '/', pos - 1);
+        // don't remove the host, i.e. http://foo.org/../foo.html
+        if (prev < 0 || (prev > 3 && path[prev - 2] == ':' && path[prev - 1] == '/'))
+            path.remove(pos, 3);
+        else
+            path.remove(prev, pos - prev + 3);
+    }
+
+    // FIXME: Shold not do this in the query part.
+    // Set refPos to -2 to mean "I haven't looked for the anchor yet".
+    // We don't want to waste a function call on the search for the the anchor
+    // in the vast majority of cases where there is no "//" in the path.
+    pos = 0;
+    int refPos = -2;
+    while ((pos = findSlashSlash(path.data(), path.size(), pos)) != -1) {
+        if (refPos == -2)
+            refPos = find(path.data(), path.size(), '#');
+        if (refPos > 0 && pos >= refPos)
+            break;
+
+        if (pos == 0 || path[pos - 1] != ':')
+            path.remove(pos);
+        else
+            pos += 2;
+    }
+
+    // FIXME: Shold not do this in the query or anchor part.
+    while ((pos = findSlashDotSlash(path.data(), path.size())) != -1)
+        path.remove(pos, 2);
+}
+
+static inline bool matchLetter(UChar c, UChar lowercaseLetter)
+{
+    return (c | 0x20) == lowercaseLetter;
+}
+
+static inline bool needsTrailingSlash(const UChar* characters, unsigned length)
+{
+    if (length < 6)
+        return false;
+    if (!matchLetter(characters[0], 'h')
+            || !matchLetter(characters[1], 't')
+            || !matchLetter(characters[2], 't')
+            || !matchLetter(characters[3], 'p'))
+        return false;
+    if (!(characters[4] == ':'
+            || (matchLetter(characters[4], 's') && characters[5] == ':')))
+        return false;
+
+    unsigned pos = characters[4] == ':' ? 5 : 6;
+
+    // Skip initial two slashes if present.
+    if (pos + 1 < length && characters[pos] == '/' && characters[pos + 1] == '/')
+        pos += 2;
+
+    // Find next slash.
+    while (pos < length && characters[pos] != '/')
+        ++pos;
+
+    return pos == length;
+}
+
+bool PageGroup::isLinkVisited(Document* document, const AtomicString& attributeURL)
+{
+    if (!m_visitedLinksPopulated) {
+        m_visitedLinksPopulated = true;
+        ASSERT(!m_pages.isEmpty());
+        (*m_pages.begin())->chrome()->client()->populateVisitedLinks();
+    }
+
+    const UChar* characters = attributeURL.characters();
+    unsigned length = attributeURL.length();
+    if (!length)
+        return false;
+
+    // FIXME: It is strange that we do not do further processing on strings that have "://" in them.
+    // That's clearly incorrect for at least these reasons:
+    //    1) The "://" could be in the query or anchor.
+    //    2) The URL's path could have a "/./" or a "/../" or a "//" sequence in it.
+
+    // FIXME: needsTrailingSlash does not properly return true for a URL that has no path, but does
+    // have a query or anchor.
+
+    bool hasColonSlashSlash = containsColonSlashSlash(characters, length);
+
+    if (hasColonSlashSlash && !needsTrailingSlash(characters, length))
+        return m_visitedLinkHashes.contains(StringImpl::computeHash(characters, length));
+
+    Vector<UChar, 512> buffer;
+
+    // This is a poor man's completeURL. Faster with less memory allocation.
+    // FIXME: It's missing a lot of what completeURL does and what KURL does.
+    // FIXME: Move this into KURL? Or Document? Even the fast version should be in the right place,
+    // rather than here.
+
+    if (hasColonSlashSlash) {
+        // FIXME: This is incorrect for URLs that have a query or anchor; the "/" needs to go at the
+        // end of the path, *before* the query or anchor.
+        buffer.append(characters, length);
+        buffer.append('/');
+        return m_visitedLinkHashes.contains(StringImpl::computeHash(buffer.data(), buffer.size()));
+    }
+
+    const KURL& baseURL = document->baseURL();
+    switch (characters[0]) {
+        case '/':
+            buffer.append(baseURL.string().characters(), baseURL.pathStart());
+            break;
+        case '#':
+            buffer.append(baseURL.string().characters(), baseURL.pathEnd());
+            break;
+        default:
+            buffer.append(baseURL.string().characters(), baseURL.pathAfterLastSlash());
+            break;
+    }
+    buffer.append(characters, length);
+    cleanPath(buffer);
+    if (needsTrailingSlash(buffer.data(), buffer.size())) {
+        // FIXME: This is incorrect for URLs that have a query or anchor; the "/" needs to go at the
+        // end of the path, *before* the query or anchor.
+        buffer.append('/');
+    }
+
+    return m_visitedLinkHashes.contains(StringImpl::computeHash(buffer.data(), buffer.size()));
+}
+
+void PageGroup::addVisitedLink(const KURL& url)
+{
+    ASSERT(!url.isEmpty());
+    m_visitedLinkHashes.add(url.string().impl()->hash());
+}
+
+void PageGroup::addVisitedLink(const UChar* characters, size_t length)
+{
+    m_visitedLinkHashes.add(StringImpl::computeHash(characters, length));
+}
+
+void PageGroup::removeVisitedLinks()
+{
+    m_visitedLinkHashes.clear();
+}
+
+void PageGroup::removeAllVisitedLinks()
+{
+    Page::removeAllVisitedLinks();
+}
+
+} // namespace WebCore
similarity index 56%
rename from WebCore/page/GlobalHistory.h
rename to WebCore/page/PageGroup.h
index 4857f6f..984f0ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#ifndef GlobalHistory_h
-#define GlobalHistory_h
+#ifndef PageGroup_h
+#define PageGroup_h
 
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
 #include <wtf/unicode/Unicode.h>
 
 namespace WebCore {
 
-    bool historyContains(const UChar* characters, unsigned length);
+    class AtomicString;
+    class Document;
+    class KURL;
+    class Page;
 
-} // namespace WebCore
+    class PageGroup : Noncopyable {
+    public:
+        PageGroup(Page*);
+
+        const HashSet<Page*>& pages() const { return m_pages; }
+
+        void addPage(Page*);
+        void removePage(Page*);
+
+        bool isLinkVisited(Document*, const AtomicString& attributeValue);
 
-#endif // GlobalHistory_h
+        void addVisitedLink(const KURL&);
+        void addVisitedLink(const UChar*, size_t);
+        void removeVisitedLinks();
+        static void removeAllVisitedLinks();
+
+    private:
+        HashSet<Page*> m_pages;
+        HashSet<unsigned> m_visitedLinkHashes;
+        bool m_visitedLinksPopulated;
+    };
+
+} // namespace WebCore
+    
+#endif // PageGroup_h
diff --git a/WebCore/page/mac/GlobalHistoryMac.mm b/WebCore/page/mac/GlobalHistoryMac.mm
deleted file mode 100644 (file)
index 466f60e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#import "config.h"
-#import "GlobalHistory.h"
-
-#import "WebCoreHistory.h"
-
-namespace WebCore {
-
-bool historyContains(const UChar* characters, unsigned length)
-{
-    // the other side of the bridge is careful not to throw exceptions here
-    return [[WebCoreHistory historyProvider] containsURL:characters length:length];
-}
-
-} // namespace WebCore
diff --git a/WebCore/page/win/GlobalHistoryWin.cpp b/WebCore/page/win/GlobalHistoryWin.cpp
deleted file mode 100644 (file)
index c81f09b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "GlobalHistory.h"
-
-#include "WebCoreHistory.h"
-
-namespace WebCore {
-
-bool historyContains(const UChar* characters, unsigned length)
-{
-    WebCoreHistoryProvider* provider = WebCoreHistory::historyProvider();
-    return provider && provider->containsURL(characters, length);
-}
-
-} // namespace WebCore
index 7abe32e..f56bf6f 100644 (file)
@@ -31,7 +31,6 @@
 #include "Editor.h"
 #include "FrameView.h"
 #include "FTPDirectoryDocument.h"
-#include "GlobalHistory.h"
 #include "KURL.h"
 #include "NotImplemented.h"
 #include "PluginDatabase.h"
@@ -58,8 +57,6 @@ Vector<char> loadResourceIntoArray(const char* resourceName)
 /* Completely empty stubs (mostly to allow DRT to run): */
 /********************************************************/
 
-bool WebCore::historyContains(const UChar*, unsigned) { return false; }
-
 PluginSet PluginDatabase::getPluginsInPaths() const { notImplemented(); return PluginSet(); }
 Vector<String> PluginDatabase::defaultPluginPaths() { notImplemented(); return Vector<String>(); }
 bool PluginDatabase::isPreferredPluginPath(const String&) { notImplemented(); return false; }
diff --git a/WebCore/platform/mac/WebCoreHistory.h b/WebCore/platform/mac/WebCoreHistory.h
deleted file mode 100644 (file)
index d99e9b1..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-@protocol WebCoreHistoryProvider <NSObject>
-- (BOOL)containsURL:(const UniChar*)unicode length:(unsigned)length;
-@end
-
-@interface WebCoreHistory : NSObject
-
-+ (void)setHistoryProvider:(id<WebCoreHistoryProvider>)h;
-+ (id<WebCoreHistoryProvider>)historyProvider;
-
-@end
diff --git a/WebCore/platform/mac/WebCoreHistory.m b/WebCore/platform/mac/WebCoreHistory.m
deleted file mode 100644 (file)
index e1d7f38..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#import "config.h"
-
-#import "WebCoreHistory.h"
-
-@implementation WebCoreHistory
-
-static id<WebCoreHistoryProvider> _historyProvider = nil;
-
-+ (void)setHistoryProvider: (id<WebCoreHistoryProvider>)h
-{
-    if (_historyProvider != h){
-        [_historyProvider release];
-        _historyProvider = [h retain];
-    }
-}
-
-+ (id<WebCoreHistoryProvider>)historyProvider
-{
-    return _historyProvider;
-}
-
-@end
index 0f25245..5d10156 100644 (file)
@@ -49,7 +49,6 @@
 #include "FileSystem.h"
 #include "FrameView.h"
 #include "GraphicsContext.h"
-#include "GlobalHistory.h"
 #include "IconLoader.h"
 #include "IntPoint.h"
 #include "KURL.h"
diff --git a/WebCore/platform/win/WebCoreHistory.cpp b/WebCore/platform/win/WebCoreHistory.cpp
deleted file mode 100644 (file)
index 1d3fdf9..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "WebCoreHistory.h"
-
-namespace WebCore {
-
-static WebCoreHistoryProvider* _historyProvider = 0;
-
-void WebCoreHistory::setHistoryProvider(WebCoreHistoryProvider* h)
-{
-    if (_historyProvider == h)
-        return;
-
-    delete _historyProvider;
-    _historyProvider = h;
-}
-
-WebCoreHistoryProvider* WebCoreHistory::historyProvider()
-{
-    return _historyProvider;
-}
-
-}
diff --git a/WebCore/platform/win/WebCoreHistory.h b/WebCore/platform/win/WebCoreHistory.h
deleted file mode 100644 (file)
index 9082b85..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
-* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
-* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef WEBCORE_HISTORY_H_
-#define WEBCORE_HISTORY_H_
-
-#include <unicode/umachine.h>
-
-namespace WebCore {
-
-class WebCoreHistoryProvider {
-public:
-    virtual bool containsURL(const UChar* unicode, unsigned length) = 0;
-};
-
-class WebCoreHistory {
-public:
-    static void setHistoryProvider(WebCoreHistoryProvider*);
-    static WebCoreHistoryProvider* historyProvider();
-};
-
-}
-
-#endif
index 1fe39af..1da137a 100755 (executable)
@@ -113,10 +113,6 @@ bool WebCore::cookiesEnabled(const Document* document) { notImplemented(); retur
 static WebCore::Cursor localCursor;
 const WebCore::Cursor& WebCore::moveCursor() { return localCursor; }
 
-namespace WebCore {
-    bool historyContains(const UChar*, unsigned) { return false; }
-}
-
 void WebCore::findWordBoundary(UChar const* str,int len,int position,int* start, int* end) { notImplemented(); *start=position; *end=position; }
 
 PluginSet PluginDatabase::getPluginsInPaths() const { notImplemented(); return PluginSet(); }
index 48802f2..8ab9af7 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-06  Darin Adler  <darin@apple.com>
+
+        * WebKit.xcodeproj/project.pbxproj: Added WebHistoryInternal.h.
+
 2008-03-06  David D. Kilzer  <ddkilzer@apple.com>
 
         Name the WebKit build phase script that generates WebKit.LP64.exp.
index bf11488..666ca47 100644 (file)
                9398112F0824BF01008DF038 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 830E81E005853AC000AD0891 /* Security.framework */; };
                93EB178D09F88D460091F8FF /* WebSystemInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 93EB178C09F88D460091F8FF /* WebSystemInterface.m */; };
                93EB178F09F88D510091F8FF /* WebSystemInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 93EB178E09F88D510091F8FF /* WebSystemInterface.h */; };
+               93FDE9330D79CAF30074F029 /* WebHistoryInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 93FDE9320D79CAF30074F029 /* WebHistoryInternal.h */; };
                A70936AF0B5608DC00CDB48E /* WebDragClient.h in Headers */ = {isa = PBXBuildFile; fileRef = A70936AD0B5608DC00CDB48E /* WebDragClient.h */; };
                A70936B00B5608DC00CDB48E /* WebDragClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = A70936AE0B5608DC00CDB48E /* WebDragClient.mm */; };
                A7D3C5BC0B5773C5002CA450 /* WebPasteboardHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D3C5BA0B5773C5002CA450 /* WebPasteboardHelper.h */; };
                93D623DD051E791F002F47DD /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = /usr/lib/libicucore.dylib; sourceTree = "<absolute>"; };
                93EB178C09F88D460091F8FF /* WebSystemInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebSystemInterface.m; sourceTree = "<group>"; };
                93EB178E09F88D510091F8FF /* WebSystemInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSystemInterface.h; sourceTree = "<group>"; };
+               93FDE9320D79CAF30074F029 /* WebHistoryInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebHistoryInternal.h; sourceTree = "<group>"; };
                9CAE9D070252A4130ECA16EA /* WebPreferencesPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebPreferencesPrivate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                9CE1F8A302A5C6F30ECA2ACD /* WebImageRendererFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebImageRendererFactory.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                9CF0E249021361B00ECA16EA /* WebFramePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebFramePrivate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                                22F219CB08D236730030E078 /* WebBackForwardListPrivate.h */,
                                65DA2608052CC18700A97B31 /* WebHistory.mm */,
                                F520FB190221DEFD01C1A525 /* WebHistory.h */,
+                               93FDE9320D79CAF30074F029 /* WebHistoryInternal.h */,
                                3944607F020F50ED0ECA1767 /* WebHistoryItem.h */,
                                39446080020F50ED0ECA1767 /* WebHistoryItem.mm */,
                                516F296F03A6C45A00CA2D3A /* WebHistoryItemInternal.h */,
                                9398109B0824BF01008DF038 /* WebViewInternal.h in Headers */,
                                939810710824BF01008DF038 /* WebViewPrivate.h in Headers */,
                                939810970824BF01008DF038 /* npfunctions.h in Headers */,
+                               93FDE9330D79CAF30074F029 /* WebHistoryInternal.h in Headers */,
                                C0167BF80D7F5DD00028696E /* WebScriptDebugger.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
index 73d44c6..279b421 100644 (file)
@@ -1,3 +1,54 @@
+2008-03-06  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mitz.
+
+        - fix http://bugs.webkit.org/show_bug.cgi?id=17526
+          REGRESSION: iframes are added to Safari's History menu
+          by separating the visited link machinery from global history
+
+        * History/WebHistory.mm: Moved WebHistoryPrivate inside this file.
+        (-[WebHistoryPrivate removeItemFromDateCaches:]): Removed the underscore from this
+        method name, since it's on a private object.
+        (-[WebHistoryPrivate removeItemForURLString:]): Added a call to the
+        PageGroup::removeAllVisitedLinks function if the last URL was removed.
+        (-[WebHistoryPrivate addItemToDateCaches:]): Removed the underscore from this
+        method name, since it's on a private object.
+        (-[WebHistoryPrivate removeAllItems]): Call PageGroup::removeAllVisitedLinks.
+        (-[WebHistoryPrivate ageLimitDate]): Removed the underscore from this
+        method name, since it's on a private object.
+        (-[WebHistoryPrivate loadHistoryGutsFromURL:savedItemsCount:collectDiscardedItemsInto:error:]):
+        Ditto.
+        (-[WebHistoryPrivate saveHistoryGuts:URL:error:]): Ditto. Also changed this
+        to correctly return the error by using the newer version of writeToURL: and
+        removed the FIXME about that.
+        (-[WebHistoryPrivate addVisitedLinksToPageGroup:]): Added. Calls addVisitedLink
+        for every link in the history.
+        (-[WebHistory saveToURL:error:]): Removed the FIXME, since we do get the error now.
+        (-[WebHistory addItem:]): Moved into the WebPrivate category.
+        (-[WebHistory addItemForURL:]): Ditto.
+        (-[WebHistory _addItemForURL:title:]): Added. Used for the normal case where we
+        create an item and already know its title.
+        (-[WebHistory ageLimitDate]): Moved into the WebPrivate category.
+        (-[WebHistory containsItemForURLString:]): Ditto.
+        (-[WebHistory removeItem:]): Ditto.
+        (-[WebHistory setLastVisitedTimeInterval:forItem:]): Ditto.
+        (-[WebHistory _itemForURLString:]): Ditto.
+        (-[WebHistory _addVisitedLinksToPageGroup:]): Added. For use only inside WebKit.
+
+        * History/WebHistoryInternal.h: Added.
+        * History/WebHistoryItemInternal.h: Tweaked formatting and includes.
+        * History/WebHistoryPrivate.h: Moved the WebHistoryPrivate class out of this header.
+        Also reorganized what was left behind.
+
+        * WebCoreSupport/WebChromeClient.h: Added populateVisitedLinks.
+        * WebCoreSupport/WebChromeClient.mm:
+        (WebChromeClient::populateVisitedLinks): Added a call to the new
+        -[WebHistory _addVisitedLinksToPageGroup:] method.
+
+        * WebCoreSupport/WebFrameLoaderClient.mm:
+        (WebFrameLoaderClient::updateGlobalHistory): Changed code to use the new
+        -[WebHistory _addItemForURL:title:] method.
+
 2008-03-05  Adam Roben  <aroben@apple.com>
 
         Rename WebCoreScriptDebuggerImp.{h,mm} to WebScriptDebugger.{h,mm}
index 6d00758..78954c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "WebHistory.h"
-#import "WebHistoryPrivate.h"
+#import "WebHistoryInternal.h"
 
-#import "WebHistoryItem.h"
 #import "WebHistoryItemInternal.h"
-#import "WebHistoryItemPrivate.h"
 #import "WebKitLogging.h"
 #import "WebNSURLExtras.h"
+#import <WebCore/KURL.h>
+#import <WebCore/Page.h>
+#import <WebCore/PageGroup.h>
 #import <Foundation/NSError.h>
 #import <JavaScriptCore/Assertions.h>
-#import <WebCore/WebCoreHistory.h>
-#import <wtf/Vector.h>
+#import <JavaScriptCore/HashMap.h>
+#import <JavaScriptCore/RetainPtr.h>
+#import <JavaScriptCore/Vector.h>
+
+using namespace WebCore;
+
+typedef int64_t WebHistoryDateKey;
+typedef HashMap<WebHistoryDateKey, RetainPtr<NSMutableArray> > DateToEntriesMap;
 
 NSString *WebHistoryItemsAddedNotification = @"WebHistoryItemsAddedNotification";
 NSString *WebHistoryItemsRemovedNotification = @"WebHistoryItemsRemovedNotification";
@@ -54,6 +60,45 @@ NSString *DatesArrayKey = @"WebHistoryDates";
 
 #define currentFileVersion 1
 
+@interface WebHistoryPrivate : NSObject {
+@private
+    NSMutableDictionary *_entriesByURL;
+    DateToEntriesMap* _entriesByDate;
+    NSMutableArray *_orderedLastVisitedDays;
+    BOOL itemLimitSet;
+    int itemLimit;
+    BOOL ageInDaysLimitSet;
+    int ageInDaysLimit;
+}
+
+- (void)addItem:(WebHistoryItem *)entry;
+- (void)addItems:(NSArray *)newEntries;
+- (BOOL)removeItem:(WebHistoryItem *)entry;
+- (BOOL)removeItems:(NSArray *)entries;
+- (BOOL)removeAllItems;
+- (void)setLastVisitedTimeInterval:(NSTimeInterval)time forItem:(WebHistoryItem *)item;
+
+- (NSArray *)orderedLastVisitedDays;
+- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)calendarDate;
+- (BOOL)containsURL:(NSURL *)URL;
+- (BOOL)containsItemForURLString:(NSString *)URLString;
+- (WebHistoryItem *)itemForURL:(NSURL *)URL;
+- (WebHistoryItem *)itemForURLString:(NSString *)URLString;
+
+- (BOOL)loadFromURL:(NSURL *)URL collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error;
+- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error;
+
+- (NSCalendarDate *)ageLimitDate;
+
+- (void)setHistoryItemLimit:(int)limit;
+- (int)historyItemLimit;
+- (void)setHistoryAgeInDaysLimit:(int)limit;
+- (int)historyAgeInDaysLimit;
+
+- (void)addVisitedLinksToPageGroup:(PageGroup&)group;
+
+@end
+
 @implementation WebHistoryPrivate
 
 #pragma mark OBJECT FRAMEWORK
@@ -69,9 +114,8 @@ NSString *DatesArrayKey = @"WebHistoryDates";
 
 - (id)init
 {
-    if (![super init]) {
+    if (![super init])
         return nil;
-    }
     
     _entriesByURL = [[NSMutableDictionary alloc] init];
     _entriesByDate = new DateToEntriesMap;
@@ -84,7 +128,6 @@ NSString *DatesArrayKey = @"WebHistoryDates";
     [_entriesByURL release];
     [_orderedLastVisitedDays release];
     delete _entriesByDate;
-    
     [super dealloc];
 }
 
@@ -156,7 +199,7 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
     [entriesForDate insertObject:entry atIndex:low];
 }
 
-- (BOOL)_removeItemFromDateCaches:(WebHistoryItem *)entry
+- (BOOL)removeItemFromDateCaches:(WebHistoryItem *)entry
 {
     WebHistoryDateKey dateKey;
     BOOL foundDate = [self findKey:&dateKey forDay:[entry lastVisitedTimeInterval]];
@@ -179,26 +222,28 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
     return YES;
 }
 
-- (BOOL)removeItemForURLString: (NSString *)URLString
+- (BOOL)removeItemForURLString:(NSString *)URLString
 {
-    WebHistoryItem *entry = [_entriesByURL objectForKey: URLString];
-    if (entry == nil) {
+    WebHistoryItem *entry = [_entriesByURL objectForKey:URLString];
+    if (!entry)
         return NO;
-    }
 
-    [_entriesByURL removeObjectForKey: URLString];
+    [_entriesByURL removeObjectForKey:URLString];
     
 #if ASSERT_DISABLED
-    [self _removeItemFromDateCaches:entry];
+    [self removeItemFromDateCaches:entry];
 #else
-    BOOL itemWasInDateCaches = [self _removeItemFromDateCaches:entry];
+    BOOL itemWasInDateCaches = [self removeItemFromDateCaches:entry];
     ASSERT(itemWasInDateCaches);
 #endif
 
+    if (![_entriesByURL count])
+        PageGroup::removeAllVisitedLinks();
+
     return YES;
 }
 
-- (void)_addItemToDateCaches:(WebHistoryItem *)entry
+- (void)addItemToDateCaches:(WebHistoryItem *)entry
 {
     WebHistoryDateKey dateKey;
     if ([self findKey:&dateKey forDay:[entry lastVisitedTimeInterval]])
@@ -235,7 +280,7 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
         [oldEntry release];
     }
 
-    [self _addItemToDateCaches:entry];
+    [self addItemToDateCaches:entry];
     [_entriesByURL setObject:entry forKey:URLString];
 }
 
@@ -244,12 +289,12 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
 #if ASSERT_DISABLED
     [self _removeItemFromDateCaches:entry];
 #else
-    BOOL entryWasPresent = [self _removeItemFromDateCaches:entry];
+    BOOL entryWasPresent = [self removeItemFromDateCaches:entry];
     ASSERT(entryWasPresent);
 #endif
     
     [entry _setLastVisitedTimeInterval:time];
-    [self _addItemToDateCaches:entry];
+    [self addItemToDateCaches:entry];
 
     // Don't send notification until entry is back in the right place in the date caches,
     // since observers might fetch history by date when they receive the notification.
@@ -257,47 +302,38 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
         postNotificationName:WebHistoryItemChangedNotification object:entry userInfo:nil];
 }
 
-- (BOOL)removeItem: (WebHistoryItem *)entry
+- (BOOL)removeItem:(WebHistoryItem *)entry
 {
-    WebHistoryItem *matchingEntry;
-    NSString *URLString;
-
-    URLString = [entry URLString];
+    NSString *URLString = [entry URLString];
 
     // If this exact object isn't stored, then make no change.
     // FIXME: Is this the right behavior if this entry isn't present, but another entry for the same URL is?
     // Maybe need to change the API to make something like removeEntryForURLString public instead.
-    matchingEntry = [_entriesByURL objectForKey: URLString];
-    if (matchingEntry != entry) {
+    WebHistoryItem *matchingEntry = [_entriesByURL objectForKey:URLString];
+    if (matchingEntry != entry)
         return NO;
-    }
 
-    [self removeItemForURLString: URLString];
+    [self removeItemForURLString:URLString];
 
     return YES;
 }
 
-- (BOOL)removeItems: (NSArray *)entries
+- (BOOL)removeItems:(NSArray *)entries
 {
-    int index, count;
-
-    count = [entries count];
-    if (count == 0) {
+    NSUInteger count = [entries count];
+    if (!count)
         return NO;
-    }
 
-    for (index = 0; index < count; ++index) {
+    for (NSUInteger index = 0; index < count; ++index)
         [self removeItem:[entries objectAtIndex:index]];
-    }
     
     return YES;
 }
 
 - (BOOL)removeAllItems
 {
-    if ([_entriesByURL count] == 0) {
+    if (_entriesByDate->isEmpty())
         return NO;
-    }
 
     _entriesByDate->clear();
     [_entriesByURL removeAllObjects];
@@ -306,23 +342,21 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
     [_orderedLastVisitedDays release];
     _orderedLastVisitedDays = nil;
 
+    PageGroup::removeAllVisitedLinks();
+
     return YES;
 }
 
 - (void)addItems:(NSArray *)newEntries
 {
-    NSEnumerator *enumerator;
-    WebHistoryItem *entry;
-
     // There is no guarantee that the incoming entries are in any particular
     // order, but if this is called with a set of entries that were created by
     // iterating through the results of orderedLastVisitedDays and orderedItemsLastVisitedOnDayy
     // then they will be ordered chronologically from newest to oldest. We can make adding them
     // faster (fewer compares) by inserting them from oldest to newest.
-    enumerator = [newEntries reverseObjectEnumerator];
-    while ((entry = [enumerator nextObject]) != nil) {
+    NSEnumerator *enumerator = [newEntries reverseObjectEnumerator];
+    while (WebHistoryItem *entry = [enumerator nextObject])
         [self addItem:entry];
-    }
 }
 
 #pragma mark DATE-BASED RETRIEVAL
@@ -349,28 +383,27 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
     return _orderedLastVisitedDays;
 }
 
-- (NSArray *)orderedItemsLastVisitedOnDay: (NSCalendarDate *)date
+- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)date
 {
     WebHistoryDateKey dateKey;
-    if ([self findKey:&dateKey forDay:[date timeIntervalSinceReferenceDate]])
-        return _entriesByDate->get(dateKey).get();
-
-    return nil;
+    if (![self findKey:&dateKey forDay:[date timeIntervalSinceReferenceDate]])
+        return nil;
+    return _entriesByDate->get(dateKey).get();
 }
 
 #pragma mark URL MATCHING
 
 - (WebHistoryItem *)itemForURLString:(NSString *)URLString
 {
-    return [_entriesByURL objectForKey: URLString];
+    return [_entriesByURL objectForKey:URLString];
 }
 
-- (BOOL)containsItemForURLString: (NSString *)URLString
+- (BOOL)containsItemForURLString:(NSString *)URLString
 {
     return [self itemForURLString:URLString] != nil;
 }
 
-- (BOOL)containsURL: (NSURL *)URL
+- (BOOL)containsURL:(NSURL *)URL
 {
     return [self itemForURLString:[URL _web_originalDataAsString]] != nil;
 }
@@ -392,7 +425,7 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
 {
     if (ageInDaysLimitSet)
         return ageInDaysLimit;
-    return [[NSUserDefaults standardUserDefaults] integerForKey: @"WebKitHistoryAgeInDaysLimit"];
+    return [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitHistoryAgeInDaysLimit"];
 }
 
 - (void)setHistoryItemLimit:(int)limit
@@ -405,12 +438,12 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
 {
     if (itemLimitSet)
         return itemLimit;
-    return [[NSUserDefaults standardUserDefaults] integerForKey: @"WebKitHistoryItemLimit"];
+    return [[NSUserDefaults standardUserDefaults] integerForKey:@"WebKitHistoryItemLimit"];
 }
 
 // Return a date that marks the age limit for history entries saved to or
 // loaded from disk. Any entry older than this item should be rejected.
-- (NSCalendarDate *)_ageLimitDate
+- (NSCalendarDate *)ageLimitDate
 {
     return [[NSCalendarDate calendarDate] dateByAddingYears:0 months:0 days:-[self historyAgeInDaysLimit]
                                                       hours:0 minutes:0 seconds:0];
@@ -440,7 +473,7 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
     return arrayRep;
 }
 
-- (BOOL)_loadHistoryGutsFromURL:(NSURL *)URL savedItemsCount:(int *)numberOfItemsLoaded collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error
+- (BOOL)loadHistoryGutsFromURL:(NSURL *)URL savedItemsCount:(int *)numberOfItemsLoaded collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error
 {
     *numberOfItemsLoaded = 0;
     NSDictionary *dictionary = nil;
@@ -474,12 +507,11 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
     NSNumber *fileVersionObject = [dictionary objectForKey:FileVersionKey];
     int fileVersion;
     // we don't trust data obtained from elsewhere, so double-check
-    if (fileVersionObject != nil && [fileVersionObject isKindOfClass:[NSNumber class]]) {
-        fileVersion = [fileVersionObject intValue];
-    } else {
+    if (!fileVersionObject || ![fileVersionObject isKindOfClass:[NSNumber class]]) {
         LOG_ERROR("history file version can't be determined, therefore not loading");
         return NO;
     }
+    fileVersion = [fileVersionObject intValue];
     if (fileVersion > currentFileVersion) {
         LOG_ERROR("history file version is %d, newer than newest known version %d, therefore not loading", fileVersion, currentFileVersion);
         return NO;
@@ -488,7 +520,7 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
     NSArray *array = [dictionary objectForKey:DatesArrayKey];
 
     int itemCountLimit = [self historyItemLimit];
-    NSTimeInterval ageLimitDate = [[self _ageLimitDate] timeIntervalSinceReferenceDate];
+    NSTimeInterval ageLimitDate = [[self ageLimitDate] timeIntervalSinceReferenceDate];
     NSEnumerator *enumerator = [array objectEnumerator];
     BOOL ageLimitPassed = NO;
     BOOL itemLimitPassed = NO;
@@ -530,150 +562,65 @@ WebHistoryDateKey timeIntervalForBeginningOfDay(NSTimeInterval interval)
 
 - (BOOL)loadFromURL:(NSURL *)URL collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error
 {
-    int numberOfItems;
-    double start, duration;
-    BOOL result;
+    double start = CFAbsoluteTimeGetCurrent();
 
-    start = CFAbsoluteTimeGetCurrent();
-    result = [self _loadHistoryGutsFromURL:URL savedItemsCount:&numberOfItems collectDiscardedItemsInto:discardedItems error:error];
+    int numberOfItems;
+    if (![self loadHistoryGutsFromURL:URL savedItemsCount:&numberOfItems collectDiscardedItemsInto:discardedItems error:error])
+        return NO;
 
-    if (result) {
-        duration = CFAbsoluteTimeGetCurrent() - start;
-        LOG(Timing, "loading %d history entries from %@ took %f seconds",
-            numberOfItems, URL, duration);
-    }
+    double duration = CFAbsoluteTimeGetCurrent() - start;
+    LOG(Timing, "loading %d history entries from %@ took %f seconds", numberOfItems, URL, duration);
 
-    return result;
+    return YES;
 }
 
-- (BOOL)_saveHistoryGuts: (int *)numberOfItemsSaved URL:(NSURL *)URL error:(NSError **)error
+- (BOOL)saveHistoryGuts:(int *)numberOfItemsSaved URL:(NSURL *)URL error:(NSError **)error
 {
     *numberOfItemsSaved = 0;
 
-    // FIXME:  Correctly report error when new API is ready.
-    if (error)
-        *error = nil;
-
     NSArray *array = [self arrayRepresentation];
     NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
         array, DatesArrayKey,
         [NSNumber numberWithInt:currentFileVersion], FileVersionKey,
         nil];
     NSData *data = [NSPropertyListSerialization dataFromPropertyList:dictionary format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil];
-    if (![data writeToURL:URL atomically:YES]) {
+    if (![data writeToURL:URL options:0 error:error]) {
         LOG_ERROR("attempt to save %@ to %@ failed", dictionary, URL);
         return NO;
     }
-    
+
     *numberOfItemsSaved = [array count];
     return YES;
 }
 
 - (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error
 {
-    int numberOfItems;
-    double start, duration;
-    BOOL result;
-
-    start = CFAbsoluteTimeGetCurrent();
-    result = [self _saveHistoryGuts: &numberOfItems URL:URL error:error];
-
-    if (result) {
-        duration = CFAbsoluteTimeGetCurrent() - start;
-        LOG(Timing, "saving %d history entries to %@ took %f seconds",
-            numberOfItems, URL, duration);
-    }
-
-    return result;
-}
-
-@end
-
-@interface _WebCoreHistoryProvider : NSObject  <WebCoreHistoryProvider> 
-{
-    WebHistory *history;
-}
-- initWithHistory: (WebHistory *)h;
-@end
+    double start = CFAbsoluteTimeGetCurrent();
 
-@implementation _WebCoreHistoryProvider
-- initWithHistory: (WebHistory *)h
-{
-    history = [h retain];
-    return self;
-}
+    int numberOfItems;
+    if (![self saveHistoryGuts:&numberOfItems URL:URL error:error])
+        return NO;
 
-static inline bool matchLetter(char c, char lowercaseLetter)
-{
-    return (c | 0x20) == lowercaseLetter;
-}
+    double duration = CFAbsoluteTimeGetCurrent() - start;
+    LOG(Timing, "saving %d history entries to %@ took %f seconds", numberOfItems, URL, duration);
 
-static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
-{
-    return (c | 0x20) == lowercaseLetter;
+    return YES;
 }
 
-#define UNICODE_BUFFER_SIZE 1024
-
-- (BOOL)containsURL:(const UniChar *)unicode length:(unsigned)length
+- (void)addVisitedLinksToPageGroup:(PageGroup&)group
 {
-    const UniChar *unicodeStr = unicode;
-    UniChar staticStrBuffer[UNICODE_BUFFER_SIZE];
-    UniChar *strBuffer = NULL;
-    BOOL needToAddSlash = FALSE;
-
-    if (length >= 6 &&
-        matchUnicodeLetter(unicode[0], 'h') &&
-        matchUnicodeLetter(unicode[1], 't') &&
-        matchUnicodeLetter(unicode[2], 't') &&
-        matchUnicodeLetter(unicode[3], 'p') &&
-        (unicode[4] == ':' 
-         || (matchUnicodeLetter(unicode[4], 's') && unicode[5] == ':'))) {
-
-        unsigned pos = unicode[4] == ':' ? 5 : 6;
-
-        // skip possible initial two slashes
-        if (pos + 1 < length && unicode[pos] == '/' && unicode[pos + 1] == '/') {
-            pos += 2;
+    NSEnumerator *enumerator = [_entriesByURL keyEnumerator];
+    while (NSString *url = [enumerator nextObject]) {
+        size_t length = [url length];
+        const UChar* characters = CFStringGetCharactersPtr(reinterpret_cast<CFStringRef>(url));
+        if (characters)
+            group.addVisitedLink(characters, length);
+        else {
+            Vector<UChar, 512> buffer(length);
+            [url getCharacters:buffer.data()];
+            group.addVisitedLink(buffer.data(), length);
         }
-
-        while (pos < length && unicode[pos] != '/') {
-            pos++;
-        }
-
-        if (pos == length) {
-            needToAddSlash = TRUE;
-        }
-    }
-
-    if (needToAddSlash) {
-        if (length + 1 <= UNICODE_BUFFER_SIZE) {
-            strBuffer = staticStrBuffer;
-        } else {
-            strBuffer = (UniChar*)malloc(sizeof(UniChar) * (length + 1));
-        }
-        memcpy(strBuffer, unicode, 2 * length);
-        strBuffer[length] = '/';
-        length++;
-
-        unicodeStr = strBuffer;
-    }
-
-    CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, unicodeStr, length, kCFAllocatorNull);
-    BOOL result = [history containsItemForURLString:(id)str];
-    CFRelease(str);
-
-    if (strBuffer != staticStrBuffer) {
-        free(strBuffer);
     }
-
-    return result;
-}
-
-- (void)dealloc
-{
-    [history release];
-    [super dealloc];
 }
 
 @end
@@ -685,13 +632,11 @@ static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
     return _sharedHistory;
 }
 
-
-+ (void)setOptionalSharedHistory: (WebHistory *)history
++ (void)setOptionalSharedHistory:(WebHistory *)history
 {
-    // FIXME Need to think about multiple instances of WebHistory per application
+    // FIXME: Need to think about multiple instances of WebHistory per application
     // and correct synchronization of history file between applications.
-    [WebCoreHistory setHistoryProvider: [[[_WebCoreHistoryProvider alloc] initWithHistory: history] autorelease]];
-    if (_sharedHistory != history){
+    if (_sharedHistory != history) {
         [_sharedHistory release];
         _sharedHistory = [history retain];
     }
@@ -699,10 +644,10 @@ static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
 
 - (id)init
 {
-    if ((self = [super init]) != nil) {
-        _historyPrivate = [[WebHistoryPrivate alloc] init];
-    }
-
+    self = [super init];
+    if (!self)
+        return nil;
+    _historyPrivate = [[WebHistoryPrivate alloc] init];
     return self;
 }
 
@@ -718,40 +663,14 @@ static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
 {
     NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:entries, WebHistoryItemsKey, nil];
     [[NSNotificationCenter defaultCenter]
-        postNotificationName: name object: self userInfo: userInfo];
+        postNotificationName:name object:self userInfo:userInfo];
 }
 
-- (WebHistoryItem *)addItemForURL: (NSURL *)URL
-{
-    WebHistoryItem *entry = [[WebHistoryItem alloc] initWithURL:URL title:nil];
-    [entry _setLastVisitedTimeInterval: [NSDate timeIntervalSinceReferenceDate]];
-    [self addItem: entry];
-    [entry release];
-    return entry;
-}
-
-
-- (void)addItem: (WebHistoryItem *)entry
-{
-    LOG (History, "adding %@", entry);
-    [_historyPrivate addItem: entry];
-    [self _sendNotification: WebHistoryItemsAddedNotification
-                    entries: [NSArray arrayWithObject:entry]];
-}
-
-- (void)removeItem: (WebHistoryItem *)entry
-{
-    if ([_historyPrivate removeItem: entry]) {
-        [self _sendNotification: WebHistoryItemsRemovedNotification
-                        entries: [NSArray arrayWithObject:entry]];
-    }
-}
-
-- (void)removeItems: (NSArray *)entries
+- (void)removeItems:(NSArray *)entries
 {
     if ([_historyPrivate removeItems:entries]) {
-        [self _sendNotification: WebHistoryItemsRemovedNotification
-                        entries: entries];
+        [self _sendNotification:WebHistoryItemsRemovedNotification
+                        entries:entries];
     }
 }
 
@@ -759,21 +678,16 @@ static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
 {
     if ([_historyPrivate removeAllItems]) {
         [[NSNotificationCenter defaultCenter]
-            postNotificationName: WebHistoryAllItemsRemovedNotification
-                          object: self];
+            postNotificationName:WebHistoryAllItemsRemovedNotification
+                          object:self];
     }
 }
 
 - (void)addItems:(NSArray *)newEntries
 {
     [_historyPrivate addItems:newEntries];
-    [self _sendNotification: WebHistoryItemsAddedNotification
-                    entries: newEntries];
-}
-
-- (void)setLastVisitedTimeInterval:(NSTimeInterval)time forItem:(WebHistoryItem *)entry
-{
-    [_historyPrivate setLastVisitedTimeInterval:time forItem:entry];
+    [self _sendNotification:WebHistoryItemsAddedNotification
+                    entries:newEntries];
 }
 
 #pragma mark DATE-BASED RETRIEVAL
@@ -783,21 +697,16 @@ static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
     return [_historyPrivate orderedLastVisitedDays];
 }
 
-- (NSArray *)orderedItemsLastVisitedOnDay: (NSCalendarDate *)date
+- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)date
 {
-    return [_historyPrivate orderedItemsLastVisitedOnDay: date];
+    return [_historyPrivate orderedItemsLastVisitedOnDay:date];
 }
 
 #pragma mark URL MATCHING
 
-- (BOOL)containsItemForURLString: (NSString *)URLString
-{
-    return [_historyPrivate containsItemForURLString: URLString];
-}
-
-- (BOOL)containsURL: (NSURL *)URL
+- (BOOL)containsURL:(NSURL *)URL
 {
-    return [_historyPrivate containsURL: URL];
+    return [_historyPrivate containsURL:URL];
 }
 
 - (WebHistoryItem *)itemForURL:(NSURL *)URL
@@ -809,41 +718,31 @@ static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
 
 - (BOOL)loadFromURL:(NSURL *)URL error:(NSError **)error
 {
-    NSMutableArray *discardedItems = [NSMutableArray array];
-    
-    if ([_historyPrivate loadFromURL:URL collectDiscardedItemsInto:discardedItems error:error]) {
-        [[NSNotificationCenter defaultCenter]
-            postNotificationName:WebHistoryLoadedNotification
-                          object:self];
-        
-        if ([discardedItems count] > 0)
-            [self _sendNotification:WebHistoryItemsDiscardedWhileLoadingNotification entries:discardedItems];
-        
-        return YES;
+    NSMutableArray *discardedItems = [[NSMutableArray alloc] init];    
+    if (![_historyPrivate loadFromURL:URL collectDiscardedItemsInto:discardedItems error:error]) {
+        [discardedItems release];
+        return NO;
     }
-    return NO;
-}
 
-- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error
-{
-    // FIXME:  Use new foundation API to get error when ready.
-    if([_historyPrivate saveToURL:URL error:error]){
-        [[NSNotificationCenter defaultCenter]
-            postNotificationName: WebHistorySavedNotification
-                          object: self];
-        return YES;
-    }
-    return NO;    
-}
+    [[NSNotificationCenter defaultCenter]
+        postNotificationName:WebHistoryLoadedNotification
+                      object:self];
 
-- (WebHistoryItem *)_itemForURLString:(NSString *)URLString
-{
-    return [_historyPrivate itemForURLString: URLString];
+    if ([discardedItems count])
+        [self _sendNotification:WebHistoryItemsDiscardedWhileLoadingNotification entries:discardedItems];
+
+    [discardedItems release];
+    return YES;
 }
 
-- (NSCalendarDate*)ageLimitDate
+- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error
 {
-    return [_historyPrivate _ageLimitDate];
+    if (![_historyPrivate saveToURL:URL error:error])
+        return NO;
+    [[NSNotificationCenter defaultCenter]
+        postNotificationName:WebHistorySavedNotification
+                      object:self];
+    return YES;
 }
 
 - (void)setHistoryItemLimit:(int)limit
@@ -867,3 +766,69 @@ static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
 }
 
 @end
+
+@implementation WebHistory (WebPrivate)
+
+- (void)addItem:(WebHistoryItem *)entry
+{
+    LOG(History, "adding %@", entry);
+    [_historyPrivate addItem:entry];
+    [self _sendNotification:WebHistoryItemsAddedNotification
+                    entries:[NSArray arrayWithObject:entry]];
+}
+
+- (WebHistoryItem *)addItemForURL:(NSURL *)URL
+{
+    WebHistoryItem *entry = [[WebHistoryItem alloc] initWithURL:URL title:nil];
+    [entry _setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate]];
+    [self addItem:entry];
+    [entry release];
+    return entry;
+}
+
+- (NSCalendarDate *)ageLimitDate
+{
+    return [_historyPrivate ageLimitDate];
+}
+
+- (BOOL)containsItemForURLString:(NSString *)URLString
+{
+    return [_historyPrivate containsItemForURLString:URLString];
+}
+
+- (void)removeItem:(WebHistoryItem *)entry
+{
+    if ([_historyPrivate removeItem:entry]) {
+        [self _sendNotification:WebHistoryItemsRemovedNotification
+                        entries:[NSArray arrayWithObject:entry]];
+    }
+}
+
+- (void)setLastVisitedTimeInterval:(NSTimeInterval)time forItem:(WebHistoryItem *)entry
+{
+    [_historyPrivate setLastVisitedTimeInterval:time forItem:entry];
+}
+
+- (WebHistoryItem *)_itemForURLString:(NSString *)URLString
+{
+    return [_historyPrivate itemForURLString:URLString];
+}
+
+@end
+
+@implementation WebHistory (WebInternal)
+
+- (void)_addItemForURL:(NSURL *)URL title:(NSString *)title
+{
+    WebHistoryItem *entry = [[WebHistoryItem alloc] initWithURL:URL title:title];
+    [entry _setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate]];
+    [self addItem:entry];
+    [entry release];
+}
+
+- (void)_addVisitedLinksToPageGroup:(WebCore::PageGroup&)group
+{
+    [_historyPrivate addVisitedLinksToPageGroup:group];
+}
+
+@end
diff --git a/WebKit/mac/History/WebHistoryInternal.h b/WebKit/mac/History/WebHistoryInternal.h
new file mode 100644 (file)
index 0000000..fa8fc7c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebHistoryPrivate.h"
+
+namespace WebCore {
+    class PageGroup;
+}
+
+@interface WebHistory (WebInternal)
+- (void)_addItemForURL:(NSURL *)URL title:(NSString *)title;
+- (void)_addVisitedLinksToPageGroup:(WebCore::PageGroup&)group;
+@end
index b2658ff..eebfe27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <Cocoa/Cocoa.h>
+#import "WebHistoryItemPrivate.h"
 
-#import <WebKit/WebBackForwardList.h>
-#import <WebKit/WebHistoryItem.h>
-#import <wtf/PassRefPtr.h>
+#import <JavaScriptCore/PassRefPtr.h>
 
 namespace WebCore {
     class HistoryItem;
@@ -56,8 +54,6 @@ extern void WKNotifyHistoryItemChanged();
 
 @end
 
-@interface WebBackForwardList (WebPrivate)
+@interface WebBackForwardList (WebInternal)
 - (void)_close;
 @end
-
-
index 724c4e5..1fe3986 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <Foundation/Foundation.h>
-
 #import <WebKit/WebHistory.h>
 
-@class WebHistoryItem;
-@class NSError;
-
-#ifdef __cplusplus
-#include <wtf/HashMap.h>
-#include <wtf/RetainPtr.h>
-
-typedef int64_t WebHistoryDateKey;
-typedef HashMap<WebHistoryDateKey, RetainPtr<NSMutableArray> > DateToEntriesMap;
-#else
-typedef struct DateToEntriesMap DateToEntriesMap;
-#endif
-
 /*
     @constant WebHistoryItemsDiscardedWhileLoadingNotification Posted from loadFromURL:error:.  
     This notification comes with a userInfo dictionary that contains the array of
-    items discarded due to the date limit or item limit.  The key for the array is WebHistoryItemsKey.
+    items discarded due to the date limit or item limit. The key for the array is WebHistoryItemsKey.
 */
-// FIXME: This notification should become API in WebHistory.h
+// FIXME: This notification should become public API.
 extern NSString *WebHistoryItemsDiscardedWhileLoadingNotification;
 
-// FIXME: The WebHistoryPrivate interface should be in WebHistoryInternal.h or inside WebHistory.m
-@interface WebHistoryPrivate : NSObject {
-@private
-    NSMutableDictionary *_entriesByURL;
-    DateToEntriesMap* _entriesByDate;
-    NSMutableArray *_orderedLastVisitedDays;
-    BOOL itemLimitSet;
-    int itemLimit;
-    BOOL ageInDaysLimitSet;
-    int ageInDaysLimit;
-}
-
-- (void)addItem:(WebHistoryItem *)entry;
-- (void)addItems:(NSArray *)newEntries;
-- (BOOL)removeItem:(WebHistoryItem *)entry;
-- (BOOL)removeItems:(NSArray *)entries;
-- (BOOL)removeAllItems;
-- (void)setLastVisitedTimeInterval:(NSTimeInterval)time forItem:(WebHistoryItem *)item;
-
-- (NSArray *)orderedLastVisitedDays;
-- (NSArray *)orderedItemsLastVisitedOnDay:(NSCalendarDate *)calendarDate;
-- (BOOL)containsItemForURLString:(NSString *)URLString;
-- (BOOL)containsURL:(NSURL *)URL;
-- (WebHistoryItem *)itemForURL:(NSURL *)URL;
-- (WebHistoryItem *)itemForURLString:(NSString *)URLString;
-
-- (BOOL)loadFromURL:(NSURL *)URL collectDiscardedItemsInto:(NSMutableArray *)discardedItems error:(NSError **)error;
-- (BOOL)saveToURL:(NSURL *)URL error:(NSError **)error;
-
-- (NSCalendarDate*)_ageLimitDate;
-
-- (void)setHistoryItemLimit:(int)limit;
-- (int)historyItemLimit;
-- (void)setHistoryAgeInDaysLimit:(int)limit;
-- (int)historyAgeInDaysLimit;
-
-@end
-
 @interface WebHistory (WebPrivate)
 
 // FIXME: The following SPI is used by Safari. Should it be made into public API?
 - (WebHistoryItem *)_itemForURLString:(NSString *)URLString;
 
-// FIXME: Safari doesn't use the following SPI, and it's used in WebKit only inside WebHistory.m.
-// Should we move it into a FileInternal category inside WebHistory.m, or do we need it for other
-// clients?
-- (void)removeItem:(WebHistoryItem *)entry;
+// FIXME: neither Safari nor WebKit use the following SPI -- do we still need them?
 - (void)addItem:(WebHistoryItem *)entry;
-- (BOOL)containsItemForURLString:(NSString *)URLString;
-
-// FIXME: Safari doesn't use the following SPI, but other WebKit classes do. Should we move it into
-// a WebHistoryInternal.h, or do we need it for other clients?
 - (WebHistoryItem *)addItemForURL:(NSURL *)URL;
-// Change date on existing item
+- (NSCalendarDate *)ageLimitDate;
+- (BOOL)containsItemForURLString:(NSString *)URLString;
+- (void)removeItem:(WebHistoryItem *)entry;
 - (void)setLastVisitedTimeInterval:(NSTimeInterval)time forItem:(WebHistoryItem *)item;
 
-// FIXME: neither Safari nor WebKit use the following SPI -- do we still need it?
-- (NSCalendarDate*)ageLimitDate;
-
 @end
index dd1e488..490a194 100644 (file)
@@ -102,6 +102,8 @@ public:
 
     virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String& databaseName);
 
+    virtual void populateVisitedLinks();
+
     virtual void dashboardRegionsChanged();
 
 private:
index 49518f5..3e4c925 100644 (file)
@@ -35,9 +35,9 @@
 #import "WebFrameView.h"
 #import "WebHTMLView.h"
 #import "WebHTMLViewPrivate.h"
+#import "WebHistoryInternal.h"
 #import "WebKitSystemInterface.h"
 #import "WebNSURLRequestExtras.h"
-#import "WebSecurityOriginPrivate.h"
 #import "WebSecurityOriginInternal.h"
 #import "WebUIDelegate.h"
 #import "WebUIDelegatePrivate.h"
@@ -49,6 +49,7 @@
 #import <WebCore/FrameLoadRequest.h>
 #import <WebCore/HitTestResult.h>
 #import <WebCore/IntRect.h>
+#import <WebCore/Page.h>
 #import <WebCore/PlatformScreen.h>
 #import <WebCore/PlatformString.h>
 #import <WebCore/ResourceRequest.h>
@@ -425,6 +426,11 @@ void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& database
         CallUIDelegate(m_webView, @selector(webView:frame:exceededDatabaseQuotaForSecurityOrigin:database:), kit(frame), webOrigin, (NSString *)databaseName);
     [webOrigin release];
 }
+    
+void WebChromeClient::populateVisitedLinks()
+{
+    [[WebHistory optionalSharedHistory] _addVisitedLinksToPageGroup:[m_webView page]->group()];
+}
 
 void WebChromeClient::dashboardRegionsChanged()
 {
index ed98274..21b27a5 100644 (file)
@@ -51,8 +51,7 @@
 #import "WebHTMLRepresentationPrivate.h"
 #import "WebHTMLViewInternal.h"
 #import "WebHistoryItemInternal.h"
-#import "WebHistoryItemPrivate.h"
-#import "WebHistoryPrivate.h"
+#import "WebHistoryInternal.h"
 #import "WebIconDatabaseInternal.h"
 #import "WebKitErrorsPrivate.h"
 #import "WebKitLogging.h"
@@ -723,10 +722,8 @@ void WebFrameLoaderClient::finalSetupForReplace(DocumentLoader* loader)
 void WebFrameLoaderClient::updateGlobalHistory(const KURL& url)
 {
     NSURL *cocoaURL = url;
-    WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:cocoaURL];
     const String& pageTitle = core(m_webFrame.get())->loader()->documentLoader()->title();
-    if (!pageTitle.isEmpty())
-        [entry setTitle:pageTitle];
+    [[WebHistory optionalSharedHistory] _addItemForURL:cocoaURL title:pageTitle];
 }
  
 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
index 17b5713..c11e0bf 100644 (file)
@@ -1,3 +1,44 @@
+2008-03-06  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mitz.
+
+        - fix http://bugs.webkit.org/show_bug.cgi?id=17526
+          REGRESSION: iframes are added to Safari's History menu
+          by separating the visited link machinery from global history
+
+        * WebCoreSupport/WebChromeClient.cpp:
+        (WebChromeClient::populateVisitedLinks): Added a call to the new
+        WebHistory::addVisitedLinksToPageGroup function.
+        * WebCoreSupport/WebChromeClient.h: Added populateVisitedLinks.
+        Also fixed the webView function to be non-virtual.
+
+        * WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebFrameLoaderClient::updateGlobalHistory): Changed to use the
+        new WebHistory::addItem function.
+        (WebFrameLoaderClient::webHistory): Changed to return a WebHistory*,
+        there's no reason to AddRef the result from this function.
+        * WebCoreSupport/WebFrameLoaderClient.h: Ditto.
+
+        * WebHistory.cpp: Removed IWebHistoryPrivate and _WebCoreHistoryProvider.
+        (WebHistory::QueryInterface): Removed IWebHistoryPrivate.
+        (sharedHistoryStorage): Added.
+        (WebHistory::sharedHistory): Added.
+        (WebHistory::optionalSharedHistory): Changed to use sharedHistory().
+        (WebHistory::setOptionalSharedHistory): Changed to require a WebHistory
+        object, not just an IWebHistory.
+        (WebHistory::removeAllItems): Call PageGroup::removeAllVisitedLinks.
+        (WebHistory::addItem): Changed parameter types since this is called with
+        arguments from WebCore -- at some point this could allow better efficiency.
+        (WebHistory::removeItemForURLString):  Call PageGroup::removeAllVisitedLinks
+        if the last URL is being removed.
+        (addVisitedLinkToPageGroup): Added. Helper. Adds a single link to a group's
+        visited link set.
+        (WebHistory::addVisitedLinksToPageGroup): Added. Adds all links to a group's
+        visited link.
+        * WebHistory.h: Removed IWebHistoryPrivate. Removed optionalSharedHistoryInternal
+        and added sharedHistory. Replaced addItemForURL and containsItemForURLString with
+        non-virtual addItem and addVisitedLinksToPageGroup functions.
+
 2008-03-05  Anders Carlsson  <andersca@apple.com>
 
         Build fix.
index ce8d6de..be54f29 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
 
 #include "WebElementPropertyBag.h"
 #include "WebFrame.h"
+#include "WebHistory.h"
 #include "WebMutableURLRequest.h"
 #include "WebSecurityOrigin.h"
 #include "WebView.h"
@@ -37,6 +38,7 @@
 #include <WebCore/FloatRect.h>
 #include <WebCore/FrameLoadRequest.h>
 #include <WebCore/FrameView.h>
+#include <WebCore/Page.h>
 #include <WebCore/WindowFeatures.h>
 #pragma warning(pop)
 
@@ -496,6 +498,11 @@ void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& database
     }
 }
 
+void WebChromeClient::populateVisitedLinks()
+{
+    WebHistory::sharedHistory()->addVisitedLinksToPageGroup(m_webView->page()->group());
+}
+
 COMPtr<IWebUIDelegate> WebChromeClient::uiDelegate()
 {
     COMPtr<IWebUIDelegate> delegate;
index 6132475..12b6512 100644 (file)
@@ -100,7 +100,9 @@ public:
 
     virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String&);
 
-    virtual WebView* webView() const { return m_webView; }
+    virtual void populateVisitedLinks();
+
+    WebView* webView() const { return m_webView; }
 
 private:
     COMPtr<IWebUIDelegate> uiDelegate();
index 9394e9e..1cb5f7b 100644 (file)
@@ -56,6 +56,7 @@
 #include <WebCore/PluginPackage.h>
 #include <WebCore/PluginView.h>
 #include <WebCore/RenderPart.h>
+#include <WebCore/ResourceHandle.h>
 #pragma warning(pop)
 
 using namespace WebCore;
@@ -428,10 +429,7 @@ void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
 
 void WebFrameLoaderClient::updateGlobalHistory(const KURL& url)
 {
-    COMPtr<WebHistory> history = webHistory();
-    if (!history)
-        return;
-    history->addItemForURL(BString(url.string()), 0);                 
+    WebHistory::sharedHistory()->addItem(url, core(m_webFrame)->loader()->documentLoader()->title());                 
 }
 
 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem*) const
@@ -697,14 +695,10 @@ void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
     m_pluginView = static_cast<PluginView*>(pluginWidget);
 }
 
-COMPtr<WebHistory> WebFrameLoaderClient::webHistory() const
+WebHistory* WebFrameLoaderClient::webHistory() const
 {
     if (m_webFrame != m_webFrame->webView()->topLevelFrame())
         return 0;
 
-    IWebHistoryPrivate* historyInternal = WebHistory::optionalSharedHistoryInternal(); // does not add a ref
-    if (!historyInternal)
-        return 0;
-
-    return COMPtr<WebHistory>(Query, historyInternal);
+    return WebHistory::sharedHistory();
 }
index dfef4ba..11b4880 100644 (file)
@@ -108,7 +108,7 @@ private:
     PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL&, const WebCore::String& name, WebCore::HTMLFrameOwnerElement*, const WebCore::String& referrer);
     void loadURLIntoChild(const WebCore::KURL&, const WebCore::String& referrer, WebFrame* childFrame);
     void receivedData(const char*, int, const WebCore::String&);
-    COMPtr<WebHistory> webHistory() const;
+    WebHistory* webHistory() const;
 
     WebFrame* m_webFrame;
 
index 16b4e48..f584c7e 100644 (file)
 #include "WebNotificationCenter.h"
 #include "WebPreferences.h"
 #include <CoreFoundation/CoreFoundation.h>
-#include <WebCore/WebCoreHistory.h>
 #pragma warning( push, 0 )
 #include <wtf/Vector.h>
+#include <WebCore/KURL.h>
+#include <WebCore/PageGroup.h>
 #pragma warning( pop )
 
+using namespace WebCore;
+
 CFStringRef DatesArrayKey = CFSTR("WebHistoryDates");
 CFStringRef FileVersionKey = CFSTR("WebHistoryFileVersion");
 
-const IID IID_IWebHistoryPrivate = { 0x3de04e59, 0x93f9, 0x4369, { 0x8b, 0x43, 0x97, 0x64, 0x58, 0xd7, 0xe3, 0x19 } };
-
 #define currentFileVersion 1
 
-class _WebCoreHistoryProvider : public WebCore::WebCoreHistoryProvider {
-public:
-    _WebCoreHistoryProvider(IWebHistory* history);
-    ~_WebCoreHistoryProvider();
-
-    virtual bool containsURL(const UChar* unicode, unsigned length);
-
-private:
-    IWebHistory* m_history;
-    IWebHistoryPrivate* m_historyPrivate;
-};
-
 static bool areEqualOrClose(double d1, double d2)
 {
     double diff = d1-d2;
@@ -97,8 +86,6 @@ static void releaseUserInfo(CFDictionaryPropertyBag* userInfo)
 
 // WebHistory -----------------------------------------------------------------
 
-IWebHistory* WebHistory::m_optionalSharedHistory = 0;
-
 WebHistory::WebHistory()
 : m_refCount(0)
 , m_preferences(0)
@@ -159,8 +146,6 @@ HRESULT STDMETHODCALLTYPE WebHistory::QueryInterface(REFIID riid, void** ppvObje
         *ppvObject = static_cast<IWebHistory*>(this);
     else if (IsEqualGUID(riid, IID_IWebHistory))
         *ppvObject = static_cast<IWebHistory*>(this);
-    else if (IsEqualGUID(riid, IID_IWebHistoryPrivate))
-        *ppvObject = static_cast<IWebHistoryPrivate*>(this);
     else
         return E_NOINTERFACE;
 
@@ -184,32 +169,30 @@ ULONG STDMETHODCALLTYPE WebHistory::Release(void)
 
 // IWebHistory ----------------------------------------------------------------
 
+static inline COMPtr<WebHistory>& sharedHistoryStorage()
+{
+    static COMPtr<WebHistory> sharedHistory;
+    return sharedHistory;
+}
+
+WebHistory* WebHistory::sharedHistory()
+{
+    return sharedHistoryStorage().get();
+}
+
 HRESULT STDMETHODCALLTYPE WebHistory::optionalSharedHistory( 
     /* [retval][out] */ IWebHistory** history)
 {
-    *history = m_optionalSharedHistory;
-    if (m_optionalSharedHistory)
-        m_optionalSharedHistory->AddRef();
-
+    *history = sharedHistory();
+    if (*history)
+        (*history)->AddRef();
     return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE WebHistory::setOptionalSharedHistory( 
     /* [in] */ IWebHistory* history)
 {
-    if (m_optionalSharedHistory) {
-        m_optionalSharedHistory->Release();
-        m_optionalSharedHistory = 0;        
-    }
-
-    _WebCoreHistoryProvider* coreHistory = 0;
-    m_optionalSharedHistory = history;
-    if (history) {
-        history->AddRef();
-        coreHistory = new _WebCoreHistoryProvider(history);
-    }
-    WebCore::WebCoreHistory::setHistoryProvider(coreHistory);
-
+    sharedHistoryStorage().query(history);
     return S_OK;
 }
 
@@ -467,6 +450,8 @@ HRESULT STDMETHODCALLTYPE WebHistory::removeAllItems( void)
     CFArrayRemoveAllValues(m_datesWithEntries.get());
     CFDictionaryRemoveAllValues(m_entriesByURL.get());
 
+    PageGroup::removeAllVisitedLinks();
+
     return postNotification(kWebHistoryAllItemsRemovedNotification);
 }
 
@@ -646,27 +631,27 @@ HRESULT WebHistory::addItem(IWebHistoryItem* entry)
     return hr;
 }
 
-HRESULT WebHistory::addItemForURL(BSTR url, BSTR title)
+void WebHistory::addItem(const KURL& url, const String& title)
 {
     COMPtr<WebHistoryItem> item(AdoptCOM, WebHistoryItem::createInstance());
     if (!item)
-        return E_FAIL;
+        return;
 
     SYSTEMTIME currentTime;
     GetSystemTime(&currentTime);
     DATE lastVisited;
     if (!SystemTimeToVariantTime(&currentTime, &lastVisited))
-        return E_FAIL;
+        return;
 
-    HRESULT hr = item->initWithURLString(url, title, 0);
+    HRESULT hr = item->initWithURLString(BString(url.string()), BString(title), 0);
     if (FAILED(hr))
-        return hr;
+        return;
 
     hr = item->setLastVisitedTimeInterval(lastVisited); // also increments visitedCount
     if (FAILED(hr))
-        return hr;
+        return;
 
-    return addItem(item.get());
+    addItem(item.get());
 }
 
 HRESULT WebHistory::itemForURLString(
@@ -694,22 +679,6 @@ HRESULT STDMETHODCALLTYPE WebHistory::itemForURL(
     return itemForURLString(urlString.get(), item);
 }
 
-HRESULT WebHistory::containsItemForURLString(
-    /* [in] */ void* urlCFString,
-    /* [retval][out] */ BOOL* contains)
-{
-    IWebHistoryItem* item = 0;
-    HRESULT hr;
-    if (SUCCEEDED(hr = itemForURLString((CFStringRef)urlCFString, &item))) {
-        *contains = TRUE;
-        // itemForURLString refs the returned item, so we need to balance that 
-        item->Release();
-    } else
-        *contains = FALSE;
-
-    return hr;
-}
-
 HRESULT WebHistory::removeItemForURLString(CFStringRef urlString)
 {
     IWebHistoryItem* entry = (IWebHistoryItem*) CFDictionaryGetValue(m_entriesByURL.get(), urlString);
@@ -719,6 +688,9 @@ HRESULT WebHistory::removeItemForURLString(CFStringRef urlString)
     HRESULT hr = removeItemFromDateCaches(entry);
     CFDictionaryRemoveValue(m_entriesByURL.get(), urlString);
 
+    if (!CFDictionaryGetCount(m_entriesByURL.get()))
+        PageGroup::removeAllVisitedLinks();
+
     return hr;
 }
 
@@ -856,101 +828,23 @@ HRESULT WebHistory::ageLimitDate(CFAbsoluteTime* time)
     return S_OK;
 }
 
-IWebHistoryPrivate* WebHistory::optionalSharedHistoryInternal()
-{
-    if (!m_optionalSharedHistory)
-        return 0;
-
-    IWebHistoryPrivate* historyPrivate;
-    if (FAILED(m_optionalSharedHistory->QueryInterface(IID_IWebHistoryPrivate, (void**)&historyPrivate)))
-        return 0;
-
-    historyPrivate->Release(); // don't add an additional ref for this internal call
-    return historyPrivate;
-}
-
-// _WebCoreHistoryProvider ----------------------------------------------------------------
-
-_WebCoreHistoryProvider::_WebCoreHistoryProvider(IWebHistory* history)
-    : m_history(history)
-    , m_historyPrivate(0)
-{
-}
-
-_WebCoreHistoryProvider::~_WebCoreHistoryProvider()
-{
-}
-
-static inline bool matchLetter(char c, char lowercaseLetter)
+static void addVisitedLinkToPageGroup(const void* key, const void*, void* context)
 {
-    return (c | 0x20) == lowercaseLetter;
-}
+    CFStringRef url = static_cast<CFStringRef>(key);
+    PageGroup* group = static_cast<PageGroup*>(context);
 
-static inline bool matchUnicodeLetter(UniChar c, UniChar lowercaseLetter)
-{
-    return (c | 0x20) == lowercaseLetter;
+    CFIndex length = CFStringGetLength(url);
+    const UChar* characters = reinterpret_cast<const UChar*>(CFStringGetCharactersPtr(url));
+    if (characters)
+        group->addVisitedLink(characters, length);
+    else {
+        Vector<UChar, 512> buffer(length);
+        CFStringGetCharacters(url, CFRangeMake(0, length), reinterpret_cast<UniChar*>(buffer.data()));
+        group->addVisitedLink(buffer.data(), length);
+    }
 }
 
-bool _WebCoreHistoryProvider::containsURL(const UChar* unicode, unsigned length)
+void WebHistory::addVisitedLinksToPageGroup(PageGroup& group)
 {
-    const int bufferSize = 1024;
-    const UChar *unicodeStr = unicode;
-    UChar staticStrBuffer[bufferSize];
-    UChar *strBuffer = 0;
-    bool needToAddSlash = false;
-
-    if (length >= 6 &&
-        matchUnicodeLetter(unicode[0], 'h') &&
-        matchUnicodeLetter(unicode[1], 't') &&
-        matchUnicodeLetter(unicode[2], 't') &&
-        matchUnicodeLetter(unicode[3], 'p') &&
-        (unicode[4] == ':' 
-        || (matchUnicodeLetter(unicode[4], 's') && unicode[5] == ':'))) {
-
-            unsigned pos = unicode[4] == ':' ? 5 : 6;
-
-            // skip possible initial two slashes
-            if (pos + 1 < length && unicode[pos] == '/' && unicode[pos + 1] == '/')
-                pos += 2;
-
-            while (pos < length && unicode[pos] != '/')
-                pos++;
-
-            if (pos == length)
-                needToAddSlash = true;
-    }
-
-    if (needToAddSlash) {
-        if (length + 1 <= bufferSize)
-            strBuffer = staticStrBuffer;
-        else
-            strBuffer = (UChar*)malloc(sizeof(UChar) * (length + 1));
-        memcpy(strBuffer, unicode, 2 * length);
-        strBuffer[length] = '/';
-        length++;
-
-        unicodeStr = strBuffer;
-    }
-
-    if (!m_historyPrivate) {
-        if (SUCCEEDED(m_history->QueryInterface(IID_IWebHistoryPrivate, (void**)&m_historyPrivate))) {
-            // don't hold a ref - we're owned by IWebHistory/IWebHistoryPrivate
-            m_historyPrivate->Release();
-        } else {
-            if (strBuffer != staticStrBuffer)
-                free(strBuffer);
-            m_historyPrivate = 0;
-            return false;
-        }
-    }
-
-    CFStringRef str = CFStringCreateWithCharactersNoCopy(NULL, (const UniChar*)unicodeStr, length, kCFAllocatorNull);
-    BOOL result = FALSE;
-    m_historyPrivate->containsItemForURLString((void*)str, &result);
-    CFRelease(str);
-
-    if (strBuffer != staticStrBuffer)
-        free(strBuffer);
-
-    return !!result;
+    CFDictionaryApplyFunction(m_entriesByURL.get(), addVisitedLinkToPageGroup, &group);
 }
index 36e3148..a49f320 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <CoreFoundation/CoreFoundation.h>
 #include <wtf/RetainPtr.h>
 
-//-----------------------------------------------------------------------------
-
-// {3DE04E59-93F9-4369-8B43-976458D7E319}
-DEFINE_GUID(IID_IWebHistoryPrivate, 0x3de04e59, 0x93f9, 0x4369, 0x8b, 0x43, 0x97, 0x64, 0x58, 0xd7, 0xe3, 0x19);
-
-interface IWebHistoryPrivate : public IUnknown
-{
-public:
-    virtual HRESULT STDMETHODCALLTYPE addItemForURL(
-        /* [in] */ BSTR url,
-        /* [in] */ BSTR title) = 0;
-    virtual HRESULT STDMETHODCALLTYPE containsItemForURLString(
-        /* [in] */ void* urlCFString,
-        /* [retval][out] */ BOOL* contains) = 0;
-};
+namespace WebCore {
+    class KURL;
+    class PageGroup;
+    class String;
+}
 
 //-----------------------------------------------------------------------------
 
 class WebPreferences;
 
-class WebHistory : public IWebHistory, IWebHistoryPrivate
-{
+class WebHistory : public IWebHistory {
 public:
     static WebHistory* createInstance();
-protected:
+private:
     WebHistory();
     ~WebHistory();
 
@@ -119,11 +108,11 @@ public:
         /* [retval][out] */ int* limit);
 
     // WebHistory
-    static IWebHistoryPrivate* optionalSharedHistoryInternal();
-    virtual HRESULT STDMETHODCALLTYPE addItemForURL(BSTR url, BSTR title);
-    virtual HRESULT STDMETHODCALLTYPE containsItemForURLString(void* urlCFString, BOOL* contains);
+    static WebHistory* sharedHistory();
+    void addItem(const WebCore::KURL&, const WebCore::String&);
+    void addVisitedLinksToPageGroup(WebCore::PageGroup&);
 
-protected:
+private:
     enum NotificationType
     {
         kWebHistoryItemsAddedNotification = 0,
@@ -150,13 +139,11 @@ protected:
     BSTR getNotificationString(NotificationType notifyType);
     HRESULT itemForURLString(CFStringRef urlString, IWebHistoryItem** item);
 
-protected:
     ULONG m_refCount;
     RetainPtr<CFMutableDictionaryRef> m_entriesByURL;
     RetainPtr<CFMutableArrayRef> m_datesWithEntries;
     RetainPtr<CFMutableArrayRef> m_entriesByDate;
     COMPtr<WebPreferences> m_preferences;
-    static IWebHistory* m_optionalSharedHistory;
 };
 
 #endif