2009-10-19  Nate Chapin  <japhet@chromium.org>

        Reviewed by Alexey Proskuryakov.

        Add support for link relations in HTMLAnchorElement and implement rel="noreferrer".

        https://bugs.webkit.org/show_bug.cgi?id=28986



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49809 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp
index 5c27c85..449e9a6 100644
--- a/WebCore/loader/FrameLoader.cpp
+++ b/WebCore/loader/FrameLoader.cpp
@@ -55,6 +55,7 @@
 #include "FrameLoaderClient.h"
 #include "FrameTree.h"
 #include "FrameView.h"
+#include "HTMLAnchorElement.h"
 #include "HTMLAppletElement.h"
 #include "HTMLFormElement.h"
 #include "HTMLFrameElement.h"
@@ -195,6 +196,7 @@
     , m_committedFirstRealDocumentLoad(false)
     , m_didPerformFirstNavigation(false)
     , m_loadingFromCachedPage(false)
+    , m_suppressOpenerInNewFrame(false)
 #ifndef NDEBUG
     , m_didDispatchDidCommitLoad(false)
 #endif
@@ -252,7 +254,7 @@
         Frame* frame = frameLoaderForFrameLookup->frame()->tree()->find(request.frameName());
         if (frame && shouldAllowNavigation(frame)) {
             if (!request.resourceRequest().url().isEmpty())
-                frame->loader()->loadFrameRequest(request, false, false, 0, 0);
+                frame->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer);
             if (Page* page = frame->page())
                 page->chrome()->focus();
             created = false;
@@ -319,11 +321,13 @@
     if (m_frame->script()->executeIfJavaScriptURL(request.url(), userGesture))
         return;
 
-    urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture);
+    urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture, SendReferrer);
 }
 
-void FrameLoader::urlSelected(const ResourceRequest& request, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture)
+void FrameLoader::urlSelected(const ResourceRequest& request, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture, ReferrerPolicy referrerPolicy)
 {
+    ASSERT(!m_suppressOpenerInNewFrame);
+
     if (m_frame->script()->executeIfJavaScriptURL(request.url(), userGesture, false))
         return;
 
@@ -333,11 +337,16 @@
 
     FrameLoadRequest frameRequest(request, target);
 
-    if (frameRequest.resourceRequest().httpReferrer().isEmpty())
+    if (referrerPolicy == NoReferrer) {
+        m_suppressOpenerInNewFrame = true;
+        setOpener(0);
+    } else if (frameRequest.resourceRequest().httpReferrer().isEmpty())
         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
     addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
 
-    loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0);
+    loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0, referrerPolicy);
+
+    m_suppressOpenerInNewFrame = false;
 }
 
 bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName)
@@ -1774,7 +1783,7 @@
 }
 
 void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList,
-    PassRefPtr<Event> event, PassRefPtr<FormState> formState)
+    PassRefPtr<Event> event, PassRefPtr<FormState> formState, ReferrerPolicy referrerPolicy)
 {    
     KURL url = request.resourceRequest().url();
 
@@ -1793,7 +1802,7 @@
         }
     }
 
-    if (SecurityOrigin::shouldHideReferrer(url, referrer))
+    if (SecurityOrigin::shouldHideReferrer(url, referrer) || referrerPolicy == NoReferrer)
         referrer = String();
     
     FrameLoadType loadType;
@@ -3464,7 +3473,8 @@
 
     mainFrame->page()->setOpenedByDOM();
     mainFrame->loader()->m_client->dispatchShow();
-    mainFrame->loader()->setOpener(frame.get());
+    if (!m_suppressOpenerInNewFrame)
+        mainFrame->loader()->setOpener(frame.get());
     mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
 }
 
diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h
index eecabca..c4a8ff7 100644
--- a/WebCore/loader/FrameLoader.h
+++ b/WebCore/loader/FrameLoader.h
@@ -105,7 +105,7 @@
     void loadURLIntoChildFrame(const KURL&, const String& referer, Frame*);
 
     void loadFrameRequest(const FrameLoadRequest&, bool lockHistory, bool lockBackForwardList,  // Called by submitForm, calls loadPostRequest and loadURL.
-        PassRefPtr<Event>, PassRefPtr<FormState>);
+        PassRefPtr<Event>, PassRefPtr<FormState>, ReferrerPolicy);
 
     void load(const ResourceRequest&, bool lockHistory);                                        // Called by WebFrame, calls load(ResourceRequest, SubstituteData).
     void load(const ResourceRequest&, const SubstituteData&, bool lockHistory);                 // Called both by WebFrame and internally, calls load(DocumentLoader*).
@@ -207,7 +207,7 @@
     void setDefersLoading(bool);
 
     void changeLocation(const KURL&, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false, bool refresh = false);
-    void urlSelected(const ResourceRequest&, const String& target, PassRefPtr<Event>, bool lockHistory, bool lockBackForwardList, bool userGesture);
+    void urlSelected(const ResourceRequest&, const String& target, PassRefPtr<Event>, bool lockHistory, bool lockBackForwardList, bool userGesture, ReferrerPolicy);
     bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName);
 
     void submitForm(const char* action, const String& url,
@@ -498,6 +498,7 @@
 
     bool m_didPerformFirstNavigation;
     bool m_loadingFromCachedPage;
+    bool m_suppressOpenerInNewFrame;
     
 #ifndef NDEBUG
     bool m_didDispatchDidCommitLoad;
diff --git a/WebCore/loader/FrameLoaderTypes.h b/WebCore/loader/FrameLoaderTypes.h
index 76299f5..e7d51c7 100644
--- a/WebCore/loader/FrameLoaderTypes.h
+++ b/WebCore/loader/FrameLoaderTypes.h
@@ -87,6 +87,11 @@
         UnloadEventPolicyUnloadOnly,
         UnloadEventPolicyUnloadAndPageHide
     };
+
+    enum ReferrerPolicy {
+        SendReferrer,
+        NoReferrer
+    };
 }
 
 #endif
diff --git a/WebCore/loader/RedirectScheduler.cpp b/WebCore/loader/RedirectScheduler.cpp
index 819cbdd..f015c12 100644
--- a/WebCore/loader/RedirectScheduler.cpp
+++ b/WebCore/loader/RedirectScheduler.cpp
@@ -277,7 +277,7 @@
         case ScheduledRedirection::historyNavigation:
             if (redirection->historySteps == 0) {
                 // Special case for go(0) from a frame -> reload only the frame
-                loader->urlSelected(loader->url(), "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture);
+                loader->urlSelected(loader->url(), "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, SendReferrer);
                 return;
             }
             // go(i!=0) from a frame navigates into the history of the frame only,
@@ -293,7 +293,7 @@
             if (!redirection->formState->sourceFrame()->loader()->shouldAllowNavigation(m_frame))
                 return;
             loader->loadFrameRequest(redirection->frameRequest, redirection->lockHistory, redirection->lockBackForwardList,
-                redirection->event, redirection->formState);
+                redirection->event, redirection->formState, SendReferrer);
             return;
     }