author | Margaret Leibovic <margaret.leibovic@gmail.com> |
Thu, 28 Oct 2010 15:00:31 -0700 | |
changeset 56685 | b642534688f81ecb743869afed185a7c000fa356 |
parent 56684 | 3b73e3b886531fae356cbbeebcf5d70023cff7f9 |
child 56686 | 91a749304ec9577cb86978ac19a2cf65f2f7cb25 |
push id | 16648 |
push user | margaret.leibovic@gmail.com |
push date | Fri, 29 Oct 2010 17:58:38 +0000 |
treeherder | mozilla-central@91a749304ec9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gavin, blocking-beta7 |
bugs | 575561 |
milestone | 2.0b8pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3980,16 +3980,37 @@ var XULBrowserWindow = { setOverLink: function (link) { // Encode bidirectional formatting characters. // (RFC 3987 sections 3.2 and 4.1 paragraph 6) link = link.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g, encodeURIComponent); gURLBar.setOverLink(link); }, + + // Called before links are navigated to to allow us to retarget them if needed. + onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) { + // Don't modify non-default targets or targets that aren't in top-level app + // tab docshells (isAppTab will be false for app tab subframes). + if (originalTarget != "" || !isAppTab) + return originalTarget; + + let docURI = linkNode.ownerDocument.documentURIObject; + try { + let docURIDomain = Services.eTLD.getBaseDomain(docURI, 0); + let linkURIDomain = Services.eTLD.getBaseDomain(linkURI, 0); + // External links from within app tabs should always open in new tabs + // instead of replacing the app tab's page (Bug 575561) + if (docURIDomain != linkURIDomain) + return "_blank"; + } catch(e) { + // If getBaseDomain fails, we return originalTarget below. + } + return originalTarget; + }, onLinkIconAvailable: function (aIconURL) { if (gProxyFavIcon && gBrowser.userTypedValue === null) PageProxySetIcon(aIconURL); // update the favicon in the URL bar }, onProgressChange: function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress,
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -186,16 +186,18 @@ if (aTab.hidden) this.showTab(aTab); this.moveTabTo(aTab, this._numPinnedTabs); aTab.setAttribute("pinned", "true"); this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); + this.getBrowserForTab(aTab).docShell.isAppTab = true; + let event = document.createEvent("Events"); event.initEvent("TabPinned", true, false); aTab.dispatchEvent(event); ]]></body> </method> <method name="unpinTab"> <parameter name="aTab"/> @@ -205,16 +207,18 @@ this.moveTabTo(aTab, this._numPinnedTabs - 1); aTab.setAttribute("fadein", "true"); aTab.removeAttribute("pinned"); aTab.style.MozMarginStart = ""; this.tabContainer._positionPinnedTabs(); this.tabContainer.adjustTabstrip(); + this.getBrowserForTab(aTab).docShell.isAppTab = false; + let event = document.createEvent("Events"); event.initEvent("TabUnpinned", true, false); aTab.dispatchEvent(event); ]]></body> </method> <method name="previewTab"> <parameter name="aTab"/>
--- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -154,17 +154,17 @@ #include "nsIApplicationCache.h" #include "nsIApplicationCacheChannel.h" #include "nsIApplicationCacheContainer.h" #include "nsIPermissionManager.h" #include "nsStreamUtils.h" #include "nsIController.h" #include "nsPICommandUpdater.h" #include "nsIDOMHTMLAnchorElement.h" -#include "nsIWebBrowserChrome2.h" +#include "nsIWebBrowserChrome3.h" #include "nsITabChild.h" #include "nsIStrictTransportSecurityService.h" // Editor-related #include "nsIEditingSession.h" #include "nsPIDOMWindow.h" #include "nsPIWindowRoot.h" @@ -706,16 +706,17 @@ nsDocShell::nsDocShell(): mAllowDNSPrefetch(PR_TRUE), mCreatingDocument(PR_FALSE), mUseErrorPages(PR_FALSE), mObserveErrorPages(PR_TRUE), mAllowAuth(PR_TRUE), mAllowKeywordFixup(PR_FALSE), mIsOffScreenBrowser(PR_FALSE), mIsActive(PR_TRUE), + mIsAppTab(PR_FALSE), mFiredUnloadEvent(PR_FALSE), mEODForCurrentDocument(PR_FALSE), mURIResultedInDocument(PR_FALSE), mIsBeingDestroyed(PR_FALSE), mIsExecutingOnLoadHandler(PR_FALSE), mIsPrintingOrPP(PR_FALSE), mSavingOldViewer(PR_FALSE) #ifdef DEBUG @@ -4798,16 +4799,30 @@ nsDocShell::SetIsActive(PRBool aIsActive NS_IMETHODIMP nsDocShell::GetIsActive(PRBool *aIsActive) { *aIsActive = mIsActive; return NS_OK; } NS_IMETHODIMP +nsDocShell::SetIsAppTab(PRBool aIsAppTab) +{ + mIsAppTab = aIsAppTab; + return NS_OK; +} + +NS_IMETHODIMP +nsDocShell::GetIsAppTab(PRBool *aIsAppTab) +{ + *aIsAppTab = mIsAppTab; + return NS_OK; +} + +NS_IMETHODIMP nsDocShell::SetVisibility(PRBool aVisibility) { if (!mContentViewer) return NS_OK; if (aVisibility) { mContentViewer->Show(); } else { @@ -11306,18 +11321,32 @@ nsDocShell::OnLinkClick(nsIContent* aCon if (!IsOKToLoadURI(aURI)) { return NS_OK; } if (aContent->IsEditable()) { return NS_OK; } + nsresult rv = NS_ERROR_FAILURE; + nsAutoString target; + + nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner); + if (browserChrome3) { + nsCOMPtr<nsIDOMNode> linkNode = do_QueryInterface(aContent); + nsAutoString oldTarget(aTargetSpec); + rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI, + linkNode, mIsAppTab, target); + } + + if (NS_FAILED(rv)) + target = aTargetSpec; + nsCOMPtr<nsIRunnable> ev = - new OnLinkClickEvent(this, aContent, aURI, aTargetSpec, + new OnLinkClickEvent(this, aContent, aURI, target.get(), aPostDataStream, aHeadersDataStream); return NS_DispatchToCurrentThread(ev); } NS_IMETHODIMP nsDocShell::OnLinkClickSync(nsIContent *aContent, nsIURI* aURI, const PRUnichar* aTargetSpec,
--- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -785,16 +785,17 @@ protected: PRPackedBool mAllowDNSPrefetch; PRPackedBool mCreatingDocument; // (should be) debugging only PRPackedBool mUseErrorPages; PRPackedBool mObserveErrorPages; PRPackedBool mAllowAuth; PRPackedBool mAllowKeywordFixup; PRPackedBool mIsOffScreenBrowser; PRPackedBool mIsActive; + PRPackedBool mIsAppTab; // This boolean is set to true right before we fire pagehide and generally // unset when we embed a new content viewer. While it's true no navigation // is allowed in this docshell. PRPackedBool mFiredUnloadEvent; // this flag is for bug #21358. a docshell may load many urls // which don't result in new documents being created (i.e. a new
--- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -66,17 +66,17 @@ interface nsIRequest; interface nsISHEntry; interface nsILayoutHistoryState; interface nsISecureBrowserUI; interface nsIDOMStorage; interface nsIPrincipal; interface nsIWebBrowserPrint; interface nsIVariant; -[scriptable, uuid(74470127-87eb-4f79-8293-1616fe9cb689)] +[scriptable, uuid(98cdbcc4-2d81-4191-a63f-b6c52085edbc)] interface nsIDocShell : nsISupports { /** * Loads a given URI. This will give priority to loading the requested URI * in the object implementing this interface. If it can't be loaded here * however, the URL dispatcher will go through its normal process of content * loading. * @@ -524,21 +524,27 @@ interface nsIDocShell : nsISupports /** * Sets whether a docshell is active. An active docshell is one that is * visible, and thus is not a good candidate for certain optimizations * like image frame discarding. Docshells are active unless told otherwise. */ attribute boolean isActive; - /** * The ID of the docshell in the session history. */ readonly attribute unsigned long long historyID; + + /** + * Sets whether a docshell is an app tab. An app tab docshell may behave + * differently than a non-app tab docshell in some cases, such as when + * handling link clicks. Docshells are not app tabs unless told otherwise. + */ + attribute boolean isAppTab; }; [uuid(5f7a2184-31b6-4d67-9c75-0c17477766e2)] interface nsIDocShell_MOZILLA_2_0_BRANCH : nsISupports { /** * Create a new about:blank document and content viewer. * @param aPrincipal the principal to use for the new document. */
--- a/embedding/browser/webBrowser/Makefile.in +++ b/embedding/browser/webBrowser/Makefile.in @@ -73,16 +73,17 @@ SDK_XPIDLSRCS = \ $(NULL) XPIDLSRCS = \ nsCWebBrowser.idl \ nsICommandHandler.idl \ nsIEmbeddingSiteWindow2.idl \ nsIContextMenuListener2.idl \ nsIWebBrowserChrome2.idl \ + nsIWebBrowserChrome3.idl \ $(NULL) CPPSRCS = \ nsDocShellTreeOwner.cpp \ nsWebBrowser.cpp \ nsCommandHandler.cpp \ nsWebBrowserContentPolicy.cpp \ nsContextMenuInfo.cpp \
new file mode 100644 --- /dev/null +++ b/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl @@ -0,0 +1,65 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Margaret Leibovic <margaret.leibovic@gmail.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#include "nsIWebBrowserChrome2.idl" +#include "nsIURI.idl" +#include "nsIDOMNode.idl" + +/** + * nsIWebBrowserChrome3 is an extension to nsIWebBrowserChrome2. + */ +[scriptable, uuid(7f2aa813-b250-4e46-afeb-97b1e91bc9a5)] +interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2 +{ + /** + * Determines the appropriate target for a link. + * + * @param originalTarget + * The original link target. + * @param linkURI + * Link destination URI. + * @param aDOMNode + * Link DOM node. + * @param isAppTab + * Whether or not the link is in an app tab. + * @returns A new link target, if appropriate. + * Otherwise returns originalTarget. + */ + AString onBeforeLinkTraversal(in AString originalTarget, + in nsIURI linkURI, + in nsIDOMNode linkNode, + in PRBool isAppTab); +};
--- a/toolkit/components/help/content/help.js +++ b/toolkit/components/help/content/help.js @@ -557,17 +557,18 @@ nsHelpStatusHandler.prototype = { }, init : function() {}, destroy : function() {}, setJSStatus : function(status) {}, setJSDefaultStatus : function(status) {}, - setOverLink : function(link, context) {} + setOverLink : function(link, context) {}, + onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {} } function UpdateBackForwardButtons() { var backBroadcaster = document.getElementById("canGoBack"); var forwardBroadcaster = document.getElementById("canGoForward"); var webNavigation = getWebNavigation(); // Avoid setting attributes on broadcasters if the value hasn't changed!
--- a/toolkit/content/Services.jsm +++ b/toolkit/content/Services.jsm @@ -125,8 +125,12 @@ XPCOMUtils.defineLazyServiceGetter(Servi XPCOMUtils.defineLazyServiceGetter(Services, "strings", "@mozilla.org/intl/stringbundle;1", "nsIStringBundleService"); XPCOMUtils.defineLazyServiceGetter(Services, "urlFormatter", "@mozilla.org/toolkit/URLFormatterService;1", "nsIURLFormatter"); + +XPCOMUtils.defineLazyServiceGetter(Services, "eTLD", + "@mozilla.org/network/effective-tld-service;1", + "nsIEffectiveTLDService");
--- a/toolkit/content/tests/chrome/findbar_window.xul +++ b/toolkit/content/tests/chrome/findbar_window.xul @@ -71,17 +71,19 @@ throw Cr.NS_NOINTERFACE; }, setJSStatus: function() { }, setJSDefaultStatus: function() { }, setOverLink: function(aStatusText, aLink) { gStatusText = aStatusText; - } + }, + + onBeforeLinkTraversal: function() { } }; function ok(condition, message) { window.opener.wrappedJSObject.SimpleTest.ok(condition, message); } function finish() { window.close(); window.opener.wrappedJSObject.SimpleTest.finish();
--- a/xpfe/appshell/public/nsIXULBrowserWindow.idl +++ b/xpfe/appshell/public/nsIXULBrowserWindow.idl @@ -33,16 +33,18 @@ * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" +#include "nsIURI.idl" +#include "nsIDOMNode.idl" interface nsIRequest; interface nsIDOMElement; /** * The nsIXULBrowserWindow supplies the methods that may be called from the * internals of the browser area to tell the containing xul window to update * its ui. @@ -60,10 +62,18 @@ interface nsIXULBrowserWindow : nsISuppo */ void setJSDefaultStatus(in AString status); /** * Tells the object implementing this function what link we are currently * over. */ void setOverLink(in AString link, in nsIDOMElement element); + + /** + * Determines the appropriate target for a link. + */ + AString onBeforeLinkTraversal(in AString originalTarget, + in nsIURI linkURI, + in nsIDOMNode linkNode, + in PRBool isAppTab); };
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp +++ b/xpfe/appshell/src/nsContentTreeOwner.cpp @@ -119,16 +119,17 @@ NS_IMPL_ADDREF(nsContentTreeOwner) NS_IMPL_RELEASE(nsContentTreeOwner) NS_INTERFACE_MAP_BEGIN(nsContentTreeOwner) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellTreeOwner) NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeOwner) NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2) + NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome3) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIWindowProvider) // NOTE: This is using aggregation because there are some properties and // method on nsIBaseWindow (which we implement) and on // nsIEmbeddingSiteWindow (which we also implement) that have the same name. // And it just so happens that we want different behavior for these methods // and properties depending on the interface through which they're called // (SetFocus() is a good example here). If it were not for that, we could @@ -426,16 +427,39 @@ nsContentTreeOwner::GetPersistence(PRBoo *aPersistSize = persistString.Find("width") >= 0 || persistString.Find("height") >= 0 ? PR_TRUE : PR_FALSE; if (aPersistSizeMode) *aPersistSizeMode = persistString.Find("sizemode") >= 0 ? PR_TRUE : PR_FALSE; return NS_OK; } //***************************************************************************** +// nsContentTreeOwner::nsIWebBrowserChrome3 +//***************************************************************************** + +NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(const nsAString &originalTarget, + nsIURI *linkURI, + nsIDOMNode *linkNode, + PRBool isAppTab, + nsAString &_retval) +{ + NS_ENSURE_STATE(mXULWindow); + + nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow; + mXULWindow->GetXULBrowserWindow(getter_AddRefs(xulBrowserWindow)); + + if (xulBrowserWindow) + return xulBrowserWindow->OnBeforeLinkTraversal(originalTarget, linkURI, + linkNode, isAppTab, _retval); + + _retval = originalTarget; + return NS_OK; +} + +//***************************************************************************** // nsContentTreeOwner::nsIWebBrowserChrome2 //***************************************************************************** NS_IMETHODIMP nsContentTreeOwner::SetStatusWithContext(PRUint32 aStatusType, const nsAString &aStatusText, nsISupports *aStatusContext) { // We only allow the status to be set from the primary content shell
--- a/xpfe/appshell/src/nsContentTreeOwner.h +++ b/xpfe/appshell/src/nsContentTreeOwner.h @@ -44,39 +44,40 @@ #include "nsCOMPtr.h" #include "nsString.h" // Interfaces Needed #include "nsIBaseWindow.h" #include "nsIDocShellTreeOwner.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" -#include "nsIWebBrowserChrome2.h" +#include "nsIWebBrowserChrome3.h" #include "nsIWindowProvider.h" class nsXULWindow; class nsSiteWindow2; class nsContentTreeOwner : public nsIDocShellTreeOwner, public nsIBaseWindow, public nsIInterfaceRequestor, - public nsIWebBrowserChrome2, + public nsIWebBrowserChrome3, public nsIWindowProvider { friend class nsXULWindow; friend class nsSiteWindow2; public: NS_DECL_ISUPPORTS NS_DECL_NSIBASEWINDOW NS_DECL_NSIDOCSHELLTREEOWNER NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIWEBBROWSERCHROME2 + NS_DECL_NSIWEBBROWSERCHROME3 NS_DECL_NSIWINDOWPROVIDER protected: nsContentTreeOwner(PRBool fPrimary); virtual ~nsContentTreeOwner(); void XULWindow(nsXULWindow* aXULWindow); nsXULWindow* XULWindow();