Bug 311007 - Add aFlags arg to onLocationChange(...), to distinguish between same-document and different-document. r=smaug, sr=bzbarsky
authorOonishi Atsushi <torisugari@gmail.com>
Thu, 10 Nov 2011 15:01:11 +0100
changeset 80151 f18be484cb5abd0b20abdd846b4448c9b5a52dc5
parent 80150 6194fd540e164405a3b61c7fe7dc5f7386b1162a
child 80152 0b200d3bd4082e97ed9c0cf7415400b34a5dce7b
push id323
push userrcampbell@mozilla.com
push dateTue, 15 Nov 2011 21:58:36 +0000
treeherderfx-team@3ea216303184 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, bzbarsky
bugs311007
milestone11.0a1
Bug 311007 - Add aFlags arg to onLocationChange(...), to distinguish between same-document and different-document. r=smaug, sr=bzbarsky
accessible/src/base/nsAccDocManager.cpp
browser/base/content/browser.js
browser/base/content/tabbrowser.xml
browser/base/content/test/browser_alltabslistener.js
browser/base/content/web-panels.js
browser/components/places/tests/browser/browser_library_middleclick.js
browser/components/shell/src/nsMacShellService.cpp
content/html/content/src/nsHTMLDNSPrefetch.cpp
content/html/content/src/nsHTMLFormElement.cpp
content/xslt/tests/buster/buster-test.js
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/test/chrome/Makefile.in
docshell/test/chrome/bug311007_window.xul
docshell/test/chrome/test_bug311007.xul
docshell/test/chrome/window.template.txt
editor/composer/src/nsEditingSession.cpp
editor/composer/test/test_bug434998.xul
editor/libeditor/html/tests/test_bug607584.xul
editor/libeditor/html/tests/test_bug616590.xul
embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
embedding/browser/webBrowser/nsWebBrowser.cpp
embedding/components/printingui/src/mac/nsPrintProgress.cpp
embedding/components/printingui/src/mac/nsPrintingPromptServiceX.mm
embedding/components/printingui/src/os2/nsPrintProgress.cpp
embedding/components/printingui/src/os2/nsPrintingPromptService.cpp
embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp
embedding/components/printingui/src/win/nsPrintProgress.cpp
embedding/components/printingui/src/win/nsPrintingPromptService.cpp
embedding/tests/winEmbed/WebBrowserChrome.cpp
layout/base/tests/chrome/printpreview_bug396024_helper.xul
layout/base/tests/chrome/printpreview_bug482976_helper.xul
layout/base/tests/chrome/printpreview_helper.xul
layout/tools/layout-debug/ui/content/layoutdebug.js
mobile/chrome/content/bindings/browser.js
security/manager/boot/src/nsSecureBrowserUIImpl.cpp
toolkit/components/downloads/nsDownloadManager.cpp
toolkit/components/downloads/nsDownloadProxy.h
toolkit/components/help/content/help.js
toolkit/components/printing/content/printPreviewProgress.js
toolkit/components/printing/content/printProgress.js
toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
toolkit/mozapps/downloads/nsHelperAppDlg.js
toolkit/mozapps/extensions/content/extensions.js
uriloader/base/nsDocLoader.cpp
uriloader/base/nsDocLoader.h
uriloader/base/nsIWebProgressListener.idl
uriloader/prefetch/nsOfflineCacheUpdateService.cpp
uriloader/prefetch/nsPrefetchService.cpp
widget/tests/TestWinTSF.cpp
xpfe/appshell/src/nsChromeTreeOwner.cpp
xpfe/appshell/src/nsWebShellWindow.cpp
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -233,17 +233,18 @@ nsAccDocManager::OnProgressChange(nsIWeb
                                   PRInt32 aMaxTotalProgress)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccDocManager::OnLocationChange(nsIWebProgress *aWebProgress,
-                                  nsIRequest *aRequest, nsIURI *aLocation)
+                                  nsIRequest *aRequest, nsIURI *aLocation,
+                                  PRUint32 aFlags)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccDocManager::OnStatusChange(nsIWebProgress *aWebProgress,
                                 nsIRequest *aRequest, nsresult aStatus,
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4581,17 +4581,17 @@ var XULBrowserWindow = {
           this.throbberElement.removeAttribute("busy");
 
         this.stopCommand.setAttribute("disabled", "true");
         CombinedStopReload.switchToReload(aRequest instanceof Ci.nsIRequest);
       }
     }
   },
 
-  onLocationChange: function (aWebProgress, aRequest, aLocationURI) {
+  onLocationChange: function (aWebProgress, aRequest, aLocationURI, aFlags) {
     var location = aLocationURI ? aLocationURI.spec : "";
     this._hostChanged = true;
 
     // Hide the form invalid popup.
     if (gFormSubmitObserver.panelIsOpen()) {
       gFormSubmitObserver.panel.hidePopup();
     }
 
@@ -5047,17 +5047,18 @@ var TabsProgressListener = {
         aBrowser.removeEventListener("pagehide", arguments.callee, true);
       }, true);
 
       // We also want to make changes to page UI for unprivileged about pages.
       BrowserOnAboutPageLoad(aWebProgress.DOMWindow.document);
     }
   },
 
-  onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
+  onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI,
+                              aFlags) {
     // Filter out any sub-frame loads
     if (aBrowser.contentWindow == aWebProgress.DOMWindow)
       FullZoom.onLocationChange(aLocationURI, false, aBrowser);
   },
 
   onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
     if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
       let brandBundle = document.getElementById("bundle_brand");
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -603,17 +603,18 @@
                 // reset cached temporary values at beginning and end
                 this.mMessage = "";
                 this.mTotalProgress = 0;
               }
               this.mStateFlags = aStateFlags;
               this.mStatus = aStatus;
             },
 
-            onLocationChange: function (aWebProgress, aRequest, aLocation) {
+            onLocationChange: function (aWebProgress, aRequest, aLocation,
+                                        aFlags) {
               // OnLocationChange is called for both the top-level content
               // and the subframes.
               let topLevel = aWebProgress.DOMWindow == this.mBrowser.contentWindow;
 
               if (topLevel) {
                 // The document loaded correctly, clear the value if we should
                 if (this.mBrowser.userTypedClear > 0)
                   this.mBrowser.userTypedValue = null;
@@ -636,17 +637,18 @@
                 if (aLocation.spec != "about:blank") {
                   autocomplete.registerOpenPage(aLocation);
                   this.mBrowser.registeredOpenURI = aLocation;
                 }
               }
 
               if (!this.mBlank) {
                 this._callProgressListeners("onLocationChange",
-                                            [aWebProgress, aRequest, aLocation]);
+                                            [aWebProgress, aRequest, aLocation,
+                                             aFlags]);
               }
 
               if (topLevel)
                 this.mBrowser.lastURI = aLocation;
             },
 
             onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
               if (this.mBlank)
@@ -885,17 +887,18 @@
 #ifdef MOZ_E10S_COMPAT
             // Bug 666801 - WebProgress support for e10s and
             // Bug 666809 - SecurityUI support for e10s
 #else
             var webProgress = this.mCurrentBrowser.webProgress;
             var securityUI = this.mCurrentBrowser.securityUI;
 
             this._callProgressListeners(null, "onLocationChange",
-                                        [webProgress, null, loc], true, false);
+                                        [webProgress, null, loc, 0], true,
+                                        false);
 
             if (securityUI) {
               this._callProgressListeners(null, "onSecurityChange",
                                           [webProgress, null, securityUI.state], true, false);
             }
 #endif
 
             var listener = this.mTabListeners[this.tabContainer.selectedIndex] || null;
--- a/browser/base/content/test/browser_alltabslistener.js
+++ b/browser/base/content/test/browser_alltabslistener.js
@@ -12,17 +12,17 @@ var gFrontProgressListener = {
   onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
     var state = "onStateChange";
     info("FrontProgress: " + state + " 0x" + aStateFlags.toString(16));
     ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener");
     is(state, gFrontNotifications[gFrontNotificationsPos], "Got a notification for the front notifications listener");
     gFrontNotificationsPos++;
   },
 
-  onLocationChange: function (aWebProgress, aRequest, aLocationURI) {
+  onLocationChange: function (aWebProgress, aRequest, aLocationURI, aFlags) {
     var state = "onLocationChange";
     info("FrontProgress: " + state + " " + aLocationURI.spec);
     ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener");
     is(state, gFrontNotifications[gFrontNotificationsPos], "Got a notification for the front notifications listener");
     gFrontNotificationsPos++;
   },
   
   onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
@@ -48,17 +48,18 @@ var gAllProgressListener = {
 
     if ((aStateFlags & gCompleteState) == gCompleteState) {
       ok(gAllNotificationsPos == gAllNotifications.length, "Saw the expected number of notifications");
       ok(gFrontNotificationsPos == gFrontNotifications.length, "Saw the expected number of frontnotifications");
       executeSoon(gNextTest);
     }
   },
 
-  onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
+  onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI,
+                              aFlags) {
     var state = "onLocationChange";
     info("AllProgress: " + state + " " + aLocationURI.spec);
     ok(aBrowser == gTestBrowser, state + " notification came from the correct browser");
     ok(gAllNotificationsPos < gAllNotifications.length, "Got an expected notification for the all notifications listener");
     is(state, gAllNotifications[gAllNotificationsPos], "Got a notification for the all notifications listener");
     gAllNotificationsPos++;
   },
   
--- a/browser/base/content/web-panels.js
+++ b/browser/base/content/web-panels.js
@@ -67,17 +67,17 @@ var panelProgressListener = {
         }
         else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
                 aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
             window.parent.document.getElementById('sidebar-throbber').removeAttribute("loading");
         }
     }
     ,
 
-    onLocationChange : function(aWebProgress, aRequest, aLocation) {
+    onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) {
         UpdateBackForwardCommands(getPanelBrowser().webNavigation);
     },
 
     onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {
     },
 
     onSecurityChange : function(aWebProgress, aRequest, aState) { 
     },
--- a/browser/components/places/tests/browser/browser_library_middleclick.js
+++ b/browser/components/places/tests/browser/browser_library_middleclick.js
@@ -59,17 +59,18 @@ var gTabsListener = {
          "We have opened " + gCurrentTest.URIs.length + " new tab(s)");
     }
 
     var tab = aEvent.target;
     is(tab.ownerDocument.defaultView, window,
        "Tab has been opened in current browser window");
   },
 
-  onLocationChange: function(aBrowser, aWebProgress, aRequest, aLocationURI) {
+  onLocationChange: function(aBrowser, aWebProgress, aRequest, aLocationURI,
+                             aFlags) {
     var spec = aLocationURI.spec;
     ok(true, spec);
     // When a new tab is opened, location is first set to "about:blank", so
     // we can ignore those calls.
     // Ignore multiple notifications for the same URI too.
     if (spec == "about:blank" || this._loadedURIs.indexOf(spec) != -1)
       return;
 
--- a/browser/components/shell/src/nsMacShellService.cpp
+++ b/browser/components/shell/src/nsMacShellService.cpp
@@ -230,17 +230,18 @@ nsMacShellService::OnProgressChange(nsIW
                                     PRInt32 aMaxTotalProgress)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMacShellService::OnLocationChange(nsIWebProgress* aWebProgress,
                                     nsIRequest* aRequest,
-                                    nsIURI* aLocation)
+                                    nsIURI* aLocation,
+                                    PRUint32 aFlags)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMacShellService::OnStatusChange(nsIWebProgress* aWebProgress,
                                   nsIRequest* aRequest,
                                   nsresult aStatus,
--- a/content/html/content/src/nsHTMLDNSPrefetch.cpp
+++ b/content/html/content/src/nsHTMLDNSPrefetch.cpp
@@ -390,17 +390,18 @@ nsHTMLDNSPrefetch::nsDeferrals::OnProgre
                                                  PRInt32 maxTotalProgress)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDNSPrefetch::nsDeferrals::OnLocationChange(nsIWebProgress* aWebProgress,
                                                  nsIRequest* aRequest,
-                                                 nsIURI *location)
+                                                 nsIURI *location,
+                                                 PRUint32 aFlags)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsHTMLDNSPrefetch::nsDeferrals::OnStatusChange(nsIWebProgress* aWebProgress,
                                                nsIRequest* aRequest,
                                                nsresult aStatus,
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -1838,17 +1838,18 @@ nsHTMLFormElement::OnProgressChange(nsIW
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLFormElement::OnLocationChange(nsIWebProgress* aWebProgress,
                                     nsIRequest* aRequest,
-                                    nsIURI* location)
+                                    nsIURI* location,
+                                    PRUint32 aFlags)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLFormElement::OnStatusChange(nsIWebProgress* aWebProgress,
                                   nsIRequest* aRequest,
--- a/content/xslt/tests/buster/buster-test.js
+++ b/content/xslt/tests/buster/buster-test.js
@@ -216,17 +216,17 @@ runItem.prototype =
             aProg.removeProgressListener(this);
             this.mRefDoc = document.getElementById('hiddenHtml').contentDocument;
             this.fileLoaded(4);
         }
     },
     onProgressChange: function(aProg, b,c,d,e,f)
     {
     },
-    onLocationChange: function(aProg, aRequest, aURI)
+    onLocationChange: function(aProg, aRequest, aURI, aFlags)
     {
     },
     onStatusChange: function(aProg, aRequest, aStatus, aMessage)
     {
     },
     onSecurityChange: function(aWebProgress, aRequest, aState)
     {
     },
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1765,27 +1765,29 @@ NS_IMETHODIMP
 nsDocShell::GetChromeEventHandler(nsIDOMEventTarget** aChromeEventHandler)
 {
     NS_ENSURE_ARG_POINTER(aChromeEventHandler);
     nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mChromeEventHandler);
     target.swap(*aChromeEventHandler);
     return NS_OK;
 }
 
-/* [noscript] void setCurrentURI (in nsIURI uri); */
+/* void setCurrentURI (in nsIURI uri); */
 NS_IMETHODIMP
 nsDocShell::SetCurrentURI(nsIURI *aURI)
 {
-    SetCurrentURI(aURI, nsnull, true);
+    // Note that securityUI will set STATE_IS_INSECURE, even if
+    // the scheme of |aURI| is "https".
+    SetCurrentURI(aURI, nsnull, true, 0);
     return NS_OK;
 }
 
 bool
 nsDocShell::SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest,
-                          bool aFireOnLocationChange)
+                          bool aFireOnLocationChange, PRUint32 aLocationFlags)
 {
 #ifdef PR_LOGGING
     if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) {
         nsCAutoString spec;
         if (aURI)
             aURI->GetSpec(spec);
         PR_LogPrint("DOCSHELL %p SetCurrentURI %s\n", this, spec.get());
     }
@@ -1819,17 +1821,17 @@ nsDocShell::SetCurrentURI(nsIURI *aURI, 
        * We don't want to send OnLocationChange notifications when
        * a subframe is being loaded for the first time, while
        * visiting a frameset page
        */
       return false; 
     }
 
     if (aFireOnLocationChange) {
-        FireOnLocationChange(this, aRequest, aURI);
+        FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
     }
     return !aFireOnLocationChange;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetCharset(char** aCharset)
 {
     NS_ENSURE_ARG_POINTER(aCharset);
@@ -5923,17 +5925,17 @@ nsDocShell::OnStateChange(nsIWebProgress
                 }
 
                 // This is a document.write(). Get the made-up url
                 // from the channel and store it in session history.
                 // Pass false for aCloneChildren, since we're creating
                 // a new DOM here.
                 rv = AddToSessionHistory(uri, wcwgChannel, nsnull, false,
                                          getter_AddRefs(mLSHE));
-                SetCurrentURI(uri, aRequest, true);
+                SetCurrentURI(uri, aRequest, true, 0);
                 // Save history state of the previous page
                 rv = PersistLayoutHistoryState();
                 // We'll never get an Embed() for this load, so just go ahead
                 // and SetHistoryEntry now.
                 SetHistoryEntry(&mOSHE, mLSHE);
             }
         
         }
@@ -5979,18 +5981,18 @@ nsDocShell::OnStateChange(nsIWebProgress
     }
     // note that redirect state changes will go through here as well, but it
     // is better to handle those in OnRedirectStateChange where more
     // information is available.
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShell::OnLocationChange(nsIWebProgress * aProgress,
-                             nsIRequest * aRequest, nsIURI * aURI)
+nsDocShell::OnLocationChange(nsIWebProgress * aProgress, nsIRequest * aRequest,
+                             nsIURI * aURI, PRUint32 aFlags)
 {
     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     return NS_OK;
 }
 
 void
 nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
                                   nsIChannel* aNewChannel,
@@ -6510,17 +6512,17 @@ nsDocShell::CreateAboutBlankContentViewe
       docFactory->CreateInstanceForDocument(NS_ISUPPORTS_CAST(nsIDocShell *, this),
                     blankDoc, "view", getter_AddRefs(viewer));
 
       // hook 'em up
       if (viewer) {
         viewer->SetContainer(static_cast<nsIContentViewerContainer *>(this));
         Embed(viewer, "", 0);
 
-        SetCurrentURI(blankDoc->GetDocumentURI(), nsnull, true);
+        SetCurrentURI(blankDoc->GetDocumentURI(), nsnull, true, 0);
         rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
       }
     }
   }
   mCreatingDocument = false;
 
   // The transient about:blank viewer doesn't have a session history entry.
   SetHistoryEntry(&mOSHE, nsnull);
@@ -7161,17 +7163,17 @@ nsDocShell::RestoreFromHistory()
 
         // Use the uri from the mLSHE we had when we entered this function
         // (which need not match the document's URI if anchors are involved),
         // since that's the history entry we're loading.  Note that if we use
         // origLSHE we don't have to worry about whether the entry in question
         // is still mLSHE or whether it's now mOSHE.
         nsCOMPtr<nsIURI> uri;
         origLSHE->GetURI(getter_AddRefs(uri));
-        SetCurrentURI(uri, document->GetChannel(), true);
+        SetCurrentURI(uri, document->GetChannel(), true, 0);
     }
 
     // This is the end of our CreateContentViewer() replacement.
     // Now we simulate a load.  First, we restore the state of the javascript
     // window object.
     nsCOMPtr<nsPIDOMWindow> privWin =
         do_GetInterface(static_cast<nsIInterfaceRequestor*>(this));
     NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface");
@@ -7500,17 +7502,17 @@ nsDocShell::CreateContentViewer(const ch
     if (++gNumberOfDocumentsLoading == 1) {
       // Hint to favor performance for the plevent notification mechanism.
       // We want the pages to load as fast as possible even if its means 
       // native messages might be starved.
       FavorPerformanceHint(true, NS_EVENT_STARVATION_DELAY_HINT);
     }
 
     if (onLocationChangeNeeded) {
-      FireOnLocationChange(this, request, mCurrentURI);
+      FireOnLocationChange(this, request, mCurrentURI, 0);
     }
   
     return NS_OK;
 }
 
 nsresult
 nsDocShell::NewContentViewerObj(const char *aContentType,
                                 nsIRequest * request, nsILoadGroup * aLoadGroup,
@@ -8360,16 +8362,21 @@ nsDocShell::InternalLoad(nsIURI * aURI,
              */
             nsCOMPtr<nsISupports> owner;
             if (mOSHE) {
                 mOSHE->GetOwner(getter_AddRefs(owner));
             }
             // Pass true for aCloneSHChildren, since we're not
             // changing documents here, so all of our subframes are
             // still relevant to the new session history entry.
+            //
+            // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
+            // flag on firing onLocationChange(...).
+            // Anyway, aCloneSHChildren param is simply reflecting
+            // doShortCircuitedLoad in this scope.
             OnNewURI(aURI, nsnull, owner, mLoadType, true, true, true);
 
             nsCOMPtr<nsIInputStream> postData;
             nsCOMPtr<nsISupports> cacheKey;
 
             if (mOSHE) {
                 /* save current position of scroller(s) (bug 59774) */
                 mOSHE->SetScrollPosition(cx, cy);
@@ -9413,18 +9420,24 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIC
             shInternal->UpdateIndex();
             rootSH->GetIndex(&mLoadedTransIndex);
 #ifdef DEBUG_PAGE_CACHE
             printf("Previous index: %d, Loaded index: %d\n\n",
                    mPreviousTransIndex, mLoadedTransIndex);
 #endif
         }
     }
+
+    // aCloneSHChildren exactly means "we are not loading a new document".
+    PRUint32 locationFlags = aCloneSHChildren?
+                                 PRUint32(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
+
     bool onLocationChangeNeeded = SetCurrentURI(aURI, aChannel,
-                                                  aFireOnLocationChange);
+                                                aFireOnLocationChange,
+                                                locationFlags);
     // Make sure to store the referrer from the channel, if any
     SetupReferrerFromChannel(aChannel);
     return onLocationChangeNeeded;
 }
 
 bool
 nsDocShell::OnLoadingSite(nsIChannel * aChannel, bool aFireOnLocationChange,
                           bool aAddToGlobalHistory)
@@ -9722,18 +9735,24 @@ nsDocShell::AddState(nsIVariant *aData, 
 
     // Step 6: If the document's URI changed, update document's URI and update
     // global history.
     //
     // We need to call FireOnLocationChange so that the browser's address bar
     // gets updated and the back button is enabled, but we only need to
     // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
     // since SetCurrentURI will call FireOnLocationChange for us.
+    //
+    // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
+    // nsnull for aRequest param to FireOnLocationChange(...). Such an update
+    // notification is allowed only when we know docshell is not loading a new
+    // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
+    // FireOnLocationChange(...) breaks security UI.
     if (!equalURIs) {
-        SetCurrentURI(newURI, nsnull, true);
+        SetCurrentURI(newURI, nsnull, true, LOCATION_CHANGE_SAME_DOCUMENT);
         document->SetDocumentURI(newURI);
 
         AddURIVisit(newURI, oldURI, oldURI, 0);
 
         // AddURIVisit doesn't set the title for the new URI in global history,
         // so do that here.
         if (mUseGlobalHistory) {
             nsCOMPtr<IHistory> history = services::GetHistoryService();
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -264,20 +264,22 @@ public:
     // ForceRefreshURI method on nsIRefreshURI, but makes sure to take
     // the timer involved out of mRefreshURIList if it's there.
     // aTimer must not be null.
     nsresult ForceRefreshURIFromTimer(nsIURI * aURI, PRInt32 aDelay,
                                       bool aMetaRefresh, nsITimer* aTimer);
 
     friend class OnLinkClickEvent;
 
-    // We need dummy OnLocationChange in some cases to update the UI.
+    // We need dummy OnLocationChange in some cases to update the UI without
+    // updating security info.
     void FireDummyOnLocationChange()
     {
-      FireOnLocationChange(this, nsnull, mCurrentURI);
+        FireOnLocationChange(this, nsnull, mCurrentURI,
+                             LOCATION_CHANGE_SAME_DOCUMENT);
     }
 
     nsresult HistoryTransactionRemoved(PRInt32 aIndex);
 protected:
     // Object Management
     virtual ~nsDocShell();
     virtual void DestroyChildren();
 
@@ -588,17 +590,18 @@ protected:
                                  nsIDocShellTreeItem* aTargetTreeItem);
 
     // Returns true if would have called FireOnLocationChange,
     // but did not because aFireOnLocationChange was false on entry.
     // In this case it is the caller's responsibility to ensure
     // FireOnLocationChange is called.
     // In all other cases false is returned.
     bool SetCurrentURI(nsIURI *aURI, nsIRequest *aRequest,
-                         bool aFireOnLocationChange);
+                       bool aFireOnLocationChange,
+                       PRUint32 aLocationFlags);
 
     // The following methods deal with saving and restoring content viewers
     // in session history.
 
     // mContentViewer points to the current content viewer associated with
     // this docshell.  When loading a new document, the content viewer is
     // either destroyed or stored into a session history entry.  To make sure
     // that destruction happens in a controlled fashion, a given content viewer
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -117,16 +117,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug456980.xul \
 		test_bug662200.xul \
 		bug662200_window.xul \
 		662200a.html \
 		662200b.html \
 		662200c.html \
 		test_bug690056.xul \
 		bug690056_window.xul \
+		test_bug311007.xul \
+		bug311007_window.xul \
 		$(NULL)
 
 _DOCSHELL_SUBHARNESS = \
     docshell_helpers.js \
     generic.html \
     $(NULL)
 
 libs:: $(_HTTP_FILES)
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/bug311007_window.xul
@@ -0,0 +1,186 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="311007Test"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        width="600"
+        height="600"
+        onload="startup();"
+        title="bug 311007 test">
+
+  <script type="application/javascript" src="docshell_helpers.js"></script>
+  <script type="application/javascript"><![CDATA[
+/*
+   Regression test for bug 283733 and bug 307027.
+
+   Bug 283733
+     "accessing a relative anchor in a secure page removes the
+      locked icon and yellow background UI"
+
+   Bug 307027
+     "Going back from secure page to error page does not clear yellow bar"
+
+ */
+
+const kDNSErrorURI = "https://example/err.html";
+const kSecureURI =
+  "https://example.com/tests/docshell/test/navigation/blank.html";
+
+/*
+  Step 1: load a network error page.   <err.html>       Not Secure
+  Step 2: load a secure page.          <blank.html>     Secure
+  Step 3: a secure page + hashchange.  <blank.html#foo> Secure     (bug 283733)
+  Step 4: go back to the error page.   <err.html>       Not Secure (bug 307027)
+ */
+
+var gListener = null;
+
+function WebProgressListener() {
+  this._callback = null;
+}
+
+WebProgressListener.prototype = {
+  QueryInterface: function(aIID) {
+    if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
+        aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
+        aIID.equals(Components.interfaces.nsISupports))
+      return this;
+    throw Components.results.NS_NOINTERFACE;
+  },
+
+  onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
+    setTimeout(this._callback, 0, aWebProgress, aRequest, aLocation, aFlags);
+  },
+
+  set callback(aVal) {
+    this._callback = aVal;
+  }
+};
+
+function startup() {
+  gListener = new WebProgressListener();
+
+  document.getElementById("content")
+          .webProgress
+          .addProgressListener(gListener,
+                               Components.interfaces.nsIWebProgress
+                                         .NOTIFY_LOCATION);
+
+  setTimeout(step1A, 0);
+}
+
+/******************************************************************************
+ * Step 1: Load an error page, and confirm UA knows it's insecure.
+ ******************************************************************************/
+
+function step1A() {
+  gListener.callback = step1B;
+  content.location = kDNSErrorURI;
+}
+
+function step1B(aWebProgress, aRequest, aLocation, aFlags) {
+  /* XXX Here we receive 2 notifications, due to bug 673752. */
+  if (!aRequest) {
+    return;
+  }
+
+  is(aLocation.spec, kDNSErrorURI, "Error page's URI (1)");
+
+  ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+                          .LOCATION_CHANGE_SAME_DOCUMENT),
+     "DocShell loaded a document (1)");
+
+  ok(!(aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+                   .securityUI.state &
+       Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+     "This is not a secure page (1)");
+
+  /* Go to step 2. */
+  setTimeout(step2A, 0);
+}
+
+/******************************************************************************
+ * Step 2: Load a HTTPS page, and confirm it's secure. 
+ ******************************************************************************/
+
+function step2A() {
+  gListener.callback = step2B;
+  content.location = kSecureURI;
+}
+
+function step2B(aWebProgress, aRequest, aLocation, aFlags) {
+  is(aLocation.spec, kSecureURI, "A URI on HTTPS (2)");
+
+  ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+                          .LOCATION_CHANGE_SAME_DOCUMENT),
+     "DocShell loaded a document (2)");
+
+  ok((aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+                  .securityUI.state &
+      Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+     "This is a secure page (2)");
+
+  /* Go to step 3. */
+  setTimeout(step3A, 0);
+}
+
+/*****************************************************************************
+ * Step 3: Trigger hashchange within a secure page, and confirm UA knows
+ *         it's secure. (Bug 283733)
+ *****************************************************************************/
+
+function step3A() {
+  gListener.callback = step3B;
+  content.location += "#foo";
+}
+
+function step3B(aWebProgress, aRequest, aLocation, aFlags) {
+  is(aLocation.spec, kSecureURI + "#foo", "hashchange on HTTPS (3)");
+
+  ok((aFlags & Components.interfaces.nsIWebProgressListener
+                         .LOCATION_CHANGE_SAME_DOCUMENT),
+     "We are in the same document as before (3)");
+
+  ok((aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+                  .securityUI.state &
+      Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+     "This is a secure page (3)");
+
+  /* Go to step 4. */
+  setTimeout(step4A, 0);
+}
+
+/*****************************************************************************
+ * Step 4: Go back from a secure page to an error page, and confirm UA knows
+ *         it's not secure. (Bug 307027)
+ *****************************************************************************/
+
+function step4A() {
+  gListener.callback = step4B;
+  content.history.go(-2);
+}
+
+function step4B(aWebProgress, aRequest, aLocation, aFlags) {
+  if (!aRequest) // See step1B(...) and bug 673752.
+    return;
+
+  is(aLocation.spec, kDNSErrorURI, "Go back to the error URI (4)");
+
+  ok(!(aFlags & Components.interfaces.nsIWebProgressListener
+                          .LOCATION_CHANGE_SAME_DOCUMENT),
+       "DocShell loaded a document (4)");
+
+  ok(!(aWebProgress.QueryInterface(Components.interfaces.nsIDocShell)
+                   .securityUI.state &
+       Components.interfaces.nsIWebProgressListener.STATE_IS_SECURE),
+     "This is not a secure page (4)");
+
+  /* End. */
+  aWebProgress.removeProgressListener(gListener);
+  delete(gListener);
+  finish();
+}
+  ]]></script>
+
+  <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_bug311007.xul
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+  href="chrome://mochikit/content/tests/SimpleTest/test.css"
+  type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=311007.xul
+-->
+<window title="Mozilla Bug 311007"
+  xmlns:html="http://www.w3.org/1999/xhtml"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <title>Test for Bug 311007</title>
+  <script type="application/javascript"
+    src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+    src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+<body  xmlns="http://www.w3.org/1999/xhtml">
+<a target="_blank"
+   href="https://bugzilla.mozilla.org/show_bug.cgi?id=311007">
+   Mozilla Bug 311007</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 311007 **/
+
+SimpleTest.waitForExplicitFinish();
+window.open("bug311007_window.xul", "bug311007",
+            "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>
--- a/docshell/test/chrome/window.template.txt
+++ b/docshell/test/chrome/window.template.txt
@@ -1,12 +1,12 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 
-<window id="303267Test"
+<window id="{BUGNUMBER}Test"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         width="600"
         height="600"
         onload="setTimeout(nextTest,0);"
         title="bug {BUGNUMBER} test">
 
   <script type="application/javascript"
   src="docshell_helpers.js">
--- a/editor/composer/src/nsEditingSession.cpp
+++ b/editor/composer/src/nsEditingSession.cpp
@@ -832,17 +832,18 @@ nsEditingSession::OnProgressChange(nsIWe
 
 /*---------------------------------------------------------------------------
 
   OnLocationChange
 
 ----------------------------------------------------------------------------*/
 NS_IMETHODIMP
 nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress, 
-                                   nsIRequest *aRequest, nsIURI *aURI)
+                                   nsIRequest *aRequest, nsIURI *aURI,
+                                   PRUint32 aFlags)
 {
   nsCOMPtr<nsIDOMWindow> domWindow;
   nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   rv = domWindow->GetDocument(getter_AddRefs(domDoc));
   NS_ENSURE_SUCCESS(rv, rv);
--- a/editor/composer/test/test_bug434998.xul
+++ b/editor/composer/test/test_bug434998.xul
@@ -73,17 +73,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 
     onProgressChange : function(aWebProgress, aRequest,
                                 aCurSelfProgress, aMaxSelfProgress,
                                 aCurTotalProgress, aMaxTotalProgress)
     {
     },
 
-    onLocationChange : function(aWebProgress, aRequest, aLocation)
+    onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
     {
     },
 
     onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
     {
     },
 
     onSecurityChange : function(aWebProgress, aRequest, aState)
--- a/editor/libeditor/html/tests/test_bug607584.xul
+++ b/editor/libeditor/html/tests/test_bug607584.xul
@@ -78,17 +78,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   
   
     onProgressChange : function(aWebProgress, aRequest,
                                 aCurSelfProgress, aMaxSelfProgress,
                                 aCurTotalProgress, aMaxTotalProgress)
       {
       },
   
-    onLocationChange : function(aWebProgress, aRequest, aLocation)
+    onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
       {
       },
   
     onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
       {
       },
   
     onSecurityChange : function(aWebProgress, aRequest, aState)
--- a/editor/libeditor/html/tests/test_bug616590.xul
+++ b/editor/libeditor/html/tests/test_bug616590.xul
@@ -68,17 +68,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 
     onProgressChange : function(aWebProgress, aRequest,
                                 aCurSelfProgress, aMaxSelfProgress,
                                 aCurTotalProgress, aMaxTotalProgress)
     {
     },
 
-    onLocationChange : function(aWebProgress, aRequest, aLocation)
+    onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
     {
     },
 
     onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
     {
     },
 
     onSecurityChange : function(aWebProgress, aRequest, aState)
--- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
@@ -718,17 +718,18 @@ nsDocShellTreeOwner::OnStateChange(nsIWe
                                    nsresult aStatus)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShellTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress,
                                       nsIRequest* aRequest,
-                                      nsIURI* aURI)
+                                      nsIURI* aURI,
+                                      PRUint32 aFlags)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsDocShellTreeOwner::OnStatusChange(nsIWebProgress* aWebProgress,
                                     nsIRequest* aRequest,
                                     nsresult aStatus,
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -847,22 +847,22 @@ NS_IMETHODIMP nsWebBrowser::OnProgressCh
     }
     if (mProgressListener)
     {
         return mProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
     }
     return NS_OK;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
-NS_IMETHODIMP nsWebBrowser::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
+NS_IMETHODIMP nsWebBrowser::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
     if (mProgressListener)
     {
-        return mProgressListener->OnLocationChange(aWebProgress, aRequest, location);
+        return mProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags);
     }
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsWebBrowser::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
     if (mProgressListener)
--- a/embedding/components/printingui/src/mac/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/mac/nsPrintProgress.cpp
@@ -252,18 +252,18 @@ NS_IMETHODIMP nsPrintProgress::OnProgres
       if (aProgressListener)
         aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
     }
   }
   
   return rv;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
-NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
+NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
   nsresult rv = NS_OK;
--- a/embedding/components/printingui/src/mac/nsPrintingPromptServiceX.mm
+++ b/embedding/components/printingui/src/mac/nsPrintingPromptServiceX.mm
@@ -131,19 +131,19 @@ nsPrintingPromptService::OnStateChange(n
 
 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
 NS_IMETHODIMP 
 nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
 {
     return NS_OK;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP 
-nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP 
 nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
--- a/embedding/components/printingui/src/os2/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/os2/nsPrintProgress.cpp
@@ -249,18 +249,18 @@ NS_IMETHODIMP nsPrintProgress::OnProgres
       if (aProgressListener)
         aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
     }
   }
   
   return rv;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
-NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
+NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
   nsresult rv = NS_OK;
--- a/embedding/components/printingui/src/os2/nsPrintingPromptService.cpp
+++ b/embedding/components/printingui/src/os2/nsPrintingPromptService.cpp
@@ -284,22 +284,22 @@ NS_IMETHODIMP
 nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
 {
   if (mWebProgressListener) {
     return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
   return NS_OK;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP 
-nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
   if (mWebProgressListener) {
-    return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location);
+    return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags);
   }
   return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP 
 nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
--- a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
@@ -252,18 +252,18 @@ NS_IMETHODIMP nsPrintProgress::OnProgres
       if (aProgressListener)
         aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
     }
   }
   
   return rv;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
-NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
+NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
   nsresult rv = NS_OK;
--- a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp
+++ b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp
@@ -303,22 +303,22 @@ NS_IMETHODIMP
 nsPrintingPromptService::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
 {
   if (mWebProgressListener) {
     return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
   return NS_OK;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP 
-nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
   if (mWebProgressListener) {
-    return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location);
+    return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags);
   }
   return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP 
 nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
--- a/embedding/components/printingui/src/win/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/win/nsPrintProgress.cpp
@@ -280,18 +280,18 @@ NS_IMETHODIMP nsPrintProgress::OnProgres
       if (aProgressListener)
         aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
     }
   }
   
   return rv;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
-NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
+NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
   nsresult rv = NS_OK;
--- a/embedding/components/printingui/src/win/nsPrintingPromptService.cpp
+++ b/embedding/components/printingui/src/win/nsPrintingPromptService.cpp
@@ -352,23 +352,23 @@ nsPrintingPromptService::OnProgressChang
 {
   if (mWebProgressListener) 
   {
       return mWebProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
   return NS_ERROR_FAILURE;
 }
 
-/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
+/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP 
-nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
+nsPrintingPromptService::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, PRUint32 aFlags)
 {
   if (mWebProgressListener) 
   {
-      return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location);
+      return mWebProgressListener->OnLocationChange(aWebProgress, aRequest, location, aFlags);
   }
   return NS_ERROR_FAILURE;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP 
 nsPrintingPromptService::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
--- a/embedding/tests/winEmbed/WebBrowserChrome.cpp
+++ b/embedding/tests/winEmbed/WebBrowserChrome.cpp
@@ -271,17 +271,18 @@ NS_IMETHODIMP WebBrowserChrome::OnStateC
     }
 
     return NS_OK;
 }
 
 
 NS_IMETHODIMP WebBrowserChrome::OnLocationChange(nsIWebProgress* aWebProgress,
                                                  nsIRequest* aRequest,
-                                                 nsIURI *location)
+                                                 nsIURI *location,
+                                                 PRUint32 aFlags)
 {
   bool isSubFrameLoad = false; // Is this a subframe load
   if (aWebProgress) {
     nsCOMPtr<nsIDOMWindow>  domWindow;
     nsCOMPtr<nsIDOMWindow>  topDomWindow;
     aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
     if (domWindow) { // Get root domWindow
       domWindow->GetTop(getter_AddRefs(topDomWindow));
--- a/layout/base/tests/chrome/printpreview_bug396024_helper.xul
+++ b/layout/base/tests/chrome/printpreview_bug396024_helper.xul
@@ -15,17 +15,17 @@ var is = window.opener.wrappedJSObject.i
 var ok = window.opener.wrappedJSObject.ok;
 var todo = window.opener.wrappedJSObject.todo;
 var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
 var gWbp;
 function printpreview() {
   gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
   var listener = {
-    onLocationChange: function(webProgress, request, location) { },
+    onLocationChange: function(webProgress, request, location, flags) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
     onStatusChange: function(webProgress, request, status, message) { },
     QueryInterface: function(iid) {
       if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
--- a/layout/base/tests/chrome/printpreview_bug482976_helper.xul
+++ b/layout/base/tests/chrome/printpreview_bug482976_helper.xul
@@ -15,17 +15,17 @@ var is = window.opener.wrappedJSObject.i
 var ok = window.opener.wrappedJSObject.ok;
 var todo = window.opener.wrappedJSObject.todo;
 var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
 var gWbp;
 function printpreview() {
   gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
   var listener = {
-    onLocationChange: function(webProgress, request, location) { },
+    onLocationChange: function(webProgress, request, location, flags) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
     onStatusChange: function(webProgress, request, status, message) { },
     QueryInterface: function(iid) {
       if (iid.equals(Components.interfaces.nsIWebProgessListener) ||
--- a/layout/base/tests/chrome/printpreview_helper.xul
+++ b/layout/base/tests/chrome/printpreview_helper.xul
@@ -22,17 +22,17 @@ var file = Components.classes["@mozilla.
              .getService(Components.interfaces.nsIProperties)
              .get("TmpD", Components.interfaces.nsILocalFile);
 filePath = file.path;
 
 function printpreview() {
   gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
   var listener = {
-    onLocationChange: function(webProgress, request, location) { },
+    onLocationChange: function(webProgress, request, location, flags) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
     onStatusChange: function(webProgress, request, status, message) { },
     QueryInterface: function(iid) {
       if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
--- a/layout/tools/layout-debug/ui/content/layoutdebug.js
+++ b/layout/tools/layout-debug/ui/content/layoutdebug.js
@@ -100,17 +100,17 @@ nsLDBBrowserContentListener.prototype = 
     },
 
   onProgressChange : function(aWebProgress, aRequest,
                               aCurSelfProgress, aMaxSelfProgress,
                               aCurTotalProgress, aMaxTotalProgress)
     {
     },
 
-  onLocationChange : function(aWebProgress, aRequest, aLocation)
+  onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags)
     {
       this.mURLBar.value = aLocation.spec;
       this.setButtonEnabled(this.mForwardButton, gBrowser.canGoForward);
       this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack);
     },
 
   onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
     {
--- a/mobile/chrome/content/bindings/browser.js
+++ b/mobile/chrome/content/bindings/browser.js
@@ -30,17 +30,17 @@ let WebProgressListener = {
     sendAsyncMessage("Content:StateChange", json);
   },
 
   onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
   },
 
   _firstPaint: false,
 
-  onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI) {
+  onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
     if (content != aWebProgress.DOMWindow)
       return;
 
     let spec = aLocationURI ? aLocationURI.spec : "";
     let location = spec.split("#")[0];
 
     let charset = content.document.characterSet;
 
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -1506,17 +1506,18 @@ nsresult nsSecureBrowserUIImpl::TellTheW
   }
 
   return NS_OK; 
 }
 
 NS_IMETHODIMP
 nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress,
                                         nsIRequest* aRequest,
-                                        nsIURI* aLocation)
+                                        nsIURI* aLocation,
+                                        PRUint32 aFlags)
 {
 #ifdef DEBUG
   nsAutoAtomic atomic(mOnStateLocationChangeReentranceDetection);
   NS_ASSERTION(mOnStateLocationChangeReentranceDetection == 1,
                "unexpected parallel nsIWebProgress OnStateChange and/or OnLocationChange notification");
 #endif
   PR_LOG(gSecureDocLog, PR_LOG_DEBUG,
          ("SecureUI:%p: OnLocationChange\n", this));
@@ -1546,19 +1547,20 @@ nsSecureBrowserUIImpl::OnLocationChange(
     if (updateIsViewSource) {
       mIsViewSource = temp_IsViewSource;
     }
     mCurrentURI = aLocation;
     window = do_QueryReferent(mWindow);
     NS_ASSERTION(window, "Window has gone away?!");
   }
 
-  // If the location change does not have a corresponding request, then we
-  // assume that it does not impact the security state.
-  if (!aRequest)
+  // When |aRequest| is null, basically we don't trust that document. But if
+  // docshell insists that the document has not changed at all, we will reuse
+  // the previous security state, no matter what |aRequest| may be.
+  if (aFlags & LOCATION_CHANGE_SAME_DOCUMENT)
     return NS_OK;
 
   // The location bar has changed, so we must update the security state.  The
   // only concern with doing this here is that a page may transition from being
   // reported as completely secure to being reported as partially secure
   // (mixed).  This may be confusing for users, and it may bother users who
   // like seeing security dialogs.  However, it seems prudent given that page
   // loading may never end in some edge cases (perhaps by a site with malicious
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -2477,17 +2477,18 @@ nsDownload::OnProgressChange(nsIWebProgr
 {
   return OnProgressChange64(aWebProgress, aRequest,
                             aCurSelfProgress, aMaxSelfProgress,
                             aCurTotalProgress, aMaxTotalProgress);
 }
 
 NS_IMETHODIMP
 nsDownload::OnLocationChange(nsIWebProgress *aWebProgress,
-                             nsIRequest *aRequest, nsIURI *aLocation)
+                             nsIRequest *aRequest, nsIURI *aLocation,
+                             PRUint32 aFlags)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDownload::OnStatusChange(nsIWebProgress *aWebProgress,
                            nsIRequest *aRequest, nsresult aStatus,
                            const PRUnichar *aMessage)
--- a/toolkit/components/downloads/nsDownloadProxy.h
+++ b/toolkit/components/downloads/nsDownloadProxy.h
@@ -118,20 +118,21 @@ public:
                                nsIRequest *aRequest, nsresult aStatus,
                                const PRUnichar *aMessage)
   {
     NS_ENSURE_TRUE(mInner, NS_ERROR_NOT_INITIALIZED);
     return mInner->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
   }
 
   NS_IMETHODIMP OnLocationChange(nsIWebProgress *aWebProgress,
-                                 nsIRequest *aRequest, nsIURI *aLocation)
+                                 nsIRequest *aRequest, nsIURI *aLocation,
+                                 PRUint32 aFlags)
   {
     NS_ENSURE_TRUE(mInner, NS_ERROR_NOT_INITIALIZED);
-    return mInner->OnLocationChange(aWebProgress, aRequest, aLocation);
+    return mInner->OnLocationChange(aWebProgress, aRequest, aLocation, aFlags);
   }
   
   NS_IMETHODIMP OnProgressChange(nsIWebProgress *aWebProgress,
                                  nsIRequest *aRequest,
                                  PRInt32 aCurSelfProgress,
                                  PRInt32 aMaxSelfProgress,
                                  PRInt32 aCurTotalProgress,
                                  PRInt32 aMaxTotalProgress)
--- a/toolkit/components/help/content/help.js
+++ b/toolkit/components/help/content/help.js
@@ -538,17 +538,17 @@ function nsHelpStatusHandler() {
 
 nsHelpStatusHandler.prototype = {
 
     onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus) {},
     onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
         aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {},
     onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) {},
     onSecurityChange : function(aWebProgress, aRequest, state) {},
-    onLocationChange : function(aWebProgress, aRequest, aLocation) {
+    onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) {
         UpdateBackForwardButtons();
     },
     QueryInterface : function(aIID) {
         if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
                 aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
                 aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
                 aIID.equals(Components.interfaces.nsISupports)) {
             return this;
--- a/toolkit/components/printing/content/printPreviewProgress.js
+++ b/toolkit/components/printing/content/printPreviewProgress.js
@@ -86,17 +86,17 @@ var progressListener = {
     var docURLStr = ellipseString(progressParams.docURL, true);
     if (docURLStr != docURL && dialog.title != null) {
       docURL = docURLStr;
       if (docTitle == "")
         dialog.title.value = docURLStr;
     }
   },
 
-  onLocationChange: function (aWebProgress, aRequest, aLocation) {},
+  onLocationChange: function (aWebProgress, aRequest, aLocation, aFlags) {},
   onSecurityChange: function (aWebProgress, aRequest, state) {},
 
   onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage)
   {
     if (aMessage)
       dialog.title.setAttribute("value", aMessage);
   },
 
--- a/toolkit/components/printing/content/printProgress.js
+++ b/toolkit/components/printing/content/printProgress.js
@@ -175,17 +175,17 @@ var progressListener = {
       {
         // Progress meter should be barber-pole in this case.
         dialog.progress.setAttribute( "mode", "undetermined" );
         // Update percentage label on progress meter.
         dialog.progressText.setAttribute("value", "");
       }
     },
 
-	  onLocationChange: function(aWebProgress, aRequest, aLocation)
+	  onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags)
     {
       // we can ignore this notification
     },
 
     onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage)
     {
       if (aMessage != "")
         dialog.title.setAttribute("value", aMessage);
--- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
+++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
@@ -218,22 +218,24 @@ nsBrowserStatusFilter::OnProgressChange(
     mDelayedProgress = true;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBrowserStatusFilter::OnLocationChange(nsIWebProgress *aWebProgress,
                                         nsIRequest *aRequest,
-                                        nsIURI *aLocation)
+                                        nsIURI *aLocation,
+                                        PRUint32 aFlags)
 {
     if (!mListener)
         return NS_OK;
 
-    return mListener->OnLocationChange(aWebProgress, aRequest, aLocation);
+    return mListener->OnLocationChange(aWebProgress, aRequest, aLocation,
+                                       aFlags);
 }
 
 NS_IMETHODIMP
 nsBrowserStatusFilter::OnStatusChange(nsIWebProgress *aWebProgress,
                                       nsIRequest *aRequest,
                                       nsresult aStatus,
                                       const PRUnichar *aMessage)
 {
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -104,17 +104,17 @@ nsUnkownContentTypeDialogProgressListene
                                 aMaxTotalProgress ) {
   },
 
 
 
   onStateChange: function( aWebProgress, aRequest, aStateFlags, aStatus ) {
   },
 
-  onLocationChange: function( aWebProgress, aRequest, aLocation ) {
+  onLocationChange: function( aWebProgress, aRequest, aLocation, aFlags ) {
   },
 
   onSecurityChange: function( aWebProgress, aRequest, state ) {
   },
 
   onRefreshAttempted: function( aWebProgress, aURI, aDelay, aSameURI ) {
     return true;
   }
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -1904,17 +1904,17 @@ var gDiscoverView = {
 
     var flags = 0;
     if (!aKeepHistory)
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY;
 
     this._browser.loadURIWithFlags(aURL, flags);
   },
 
-  onLocationChange: function(aWebProgress, aRequest, aLocation) {
+  onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
     // Ignore the about:blank load
     if (aLocation.spec == "about:blank")
       return;
 
     // When using the real session history the inner-frame will update the
     // session history automatically, if using the fake history though it must
     // be manually updated
     if (gHistory == FakeHistory) {
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -1386,17 +1386,18 @@ void nsDocLoader::DoFireOnStateChange(ns
   mListenerInfoList.Compact();
 }
 
 
 
 void
 nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress,
                                   nsIRequest* aRequest,
-                                  nsIURI *aUri)
+                                  nsIURI *aUri,
+                                  PRUint32 aFlags)
 {
   /*                                                                           
    * First notify any listeners of the new state info...
    *
    * Operate the elements from back to front so that if items get
    * get removed from the list it won't affect our iteration
    */
   nsCOMPtr<nsIWebProgressListener> listener;
@@ -1413,24 +1414,24 @@ nsDocLoader::FireOnLocationChange(nsIWeb
     listener = do_QueryReferent(info->mWeakListener);
     if (!listener) {
       // the listener went away. gracefully pull it out of the list.
       mListenerInfoList.RemoveElementAt(count);
       delete info;
       continue;
     }
 
-    listener->OnLocationChange(aWebProgress, aRequest, aUri);
+    listener->OnLocationChange(aWebProgress, aRequest, aUri, aFlags);
   }
 
   mListenerInfoList.Compact();
 
   // Pass the notification up to the parent...
   if (mParent) {
-    mParent->FireOnLocationChange(aWebProgress, aRequest, aUri);
+    mParent->FireOnLocationChange(aWebProgress, aRequest, aUri, aFlags);
   }
 }
 
 void
 nsDocLoader::FireOnStatusChange(nsIWebProgress* aWebProgress,
                                 nsIRequest* aRequest,
                                 nsresult aStatus,
                                 const PRUnichar* aMessage)
--- a/uriloader/base/nsDocLoader.h
+++ b/uriloader/base/nsDocLoader.h
@@ -180,17 +180,18 @@ protected:
 
     void FireOnStatusChange(nsIWebProgress *aWebProgress,
                             nsIRequest *aRequest,
                             nsresult aStatus,
                             const PRUnichar* aMessage);
 
     void FireOnLocationChange(nsIWebProgress* aWebProgress,
                               nsIRequest* aRequest,
-                              nsIURI *aUri);
+                              nsIURI *aUri,
+                              PRUint32 aFlags);
 
     bool RefreshAttempted(nsIWebProgress* aWebProgress,
                             nsIURI *aURI,
                             PRInt32 aDelay,
                             bool aSameURI);
 
     // this function is overridden by the docshell, it is provided so that we
     // can pass more information about redirect state (the normal OnStateChange
--- a/uriloader/base/nsIWebProgressListener.idl
+++ b/uriloader/base/nsIWebProgressListener.idl
@@ -46,17 +46,17 @@ interface nsIURI;
 
 /**
  * The nsIWebProgressListener interface is implemented by clients wishing to
  * listen in on the progress associated with the loading of asynchronous
  * requests in the context of a nsIWebProgress instance as well as any child
  * nsIWebProgress instances.  nsIWebProgress.idl describes the parent-child
  * relationship of nsIWebProgress instances.
  */
-[scriptable, uuid(570F39D1-EFD0-11d3-B093-00A024FFC08C)]
+[scriptable, uuid(a0cda7e4-c6ca-11e0-b6a5-001320257da5)]
 interface nsIWebProgressListener : nsISupports
 {
   /**
    * State Transition Flags
    *
    * These flags indicate the various states that requests may transition
    * through as they are being loaded.  These flags are mutually exclusive.
    *
@@ -298,33 +298,47 @@ interface nsIWebProgressListener : nsISu
   void onProgressChange(in nsIWebProgress aWebProgress,
                         in nsIRequest aRequest,
                         in long aCurSelfProgress,
                         in long aMaxSelfProgress,
                         in long aCurTotalProgress,
                         in long aMaxTotalProgress);
 
   /**
+   * Flags for onLocationChange
+   *
+   * LOCATION_CHANGE_SAME_DOCUMENT
+   *   This flag is on when |aWebProgress| did not load a new document. 
+   *   For example, the location change is due to an anchor scroll or a
+   *   pushState/popState/replaceState.
+   */
+  const unsigned long LOCATION_CHANGE_SAME_DOCUMENT   = 0x00000001;
+
+  /**
    * Called when the location of the window being watched changes.  This is not
    * when a load is requested, but rather once it is verified that the load is
    * going to occur in the given window.  For instance, a load that starts in a
    * window might send progress and status messages for the new site, but it
    * will not send the onLocationChange until we are sure that we are loading
    * this new page here.
    *
    * @param aWebProgress
    *        The nsIWebProgress instance that fired the notification.
    * @param aRequest
    *        The associated nsIRequest.  This may be null in some cases.
    * @param aLocation
    *        The URI of the location that is being loaded.
+   * @param aFlags
+   *        This is a value which explains the situation or the reason why
+   *        the location has changed.
    */
   void onLocationChange(in nsIWebProgress aWebProgress,
                         in nsIRequest aRequest,
-                        in nsIURI aLocation);
+                        in nsIURI aLocation,
+                        [optional] in unsigned long aFlags);
 
   /**
    * Notification that the status of a request has changed.  The status message
    * is intended to be displayed to the user (e.g., in the status bar of the
    * browser).
    *
    * @param aWebProgress
    *        The nsIWebProgress instance that fired the notification.
--- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
@@ -201,17 +201,18 @@ nsOfflineCachePendingUpdate::OnStateChan
     NS_RELEASE_THIS();
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsOfflineCachePendingUpdate::OnLocationChange(nsIWebProgress* aWebProgress,
                                               nsIRequest* aRequest,
-                                              nsIURI *location)
+                                              nsIURI *location,
+                                              PRUint32 aFlags)
 {
     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsOfflineCachePendingUpdate::OnStatusChange(nsIWebProgress* aWebProgress,
                                             nsIRequest* aRequest,
--- a/uriloader/prefetch/nsPrefetchService.cpp
+++ b/uriloader/prefetch/nsPrefetchService.cpp
@@ -893,17 +893,18 @@ nsPrefetchService::OnStateChange(nsIWebP
             
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsPrefetchService::OnLocationChange(nsIWebProgress* aWebProgress,
                                     nsIRequest* aRequest,
-                                    nsIURI *location)
+                                    nsIURI *location,
+                                    PRUint32 aFlags)
 {
     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsPrefetchService::OnStatusChange(nsIWebProgress* aWebProgress,
                                   nsIRequest* aRequest,
--- a/widget/tests/TestWinTSF.cpp
+++ b/widget/tests/TestWinTSF.cpp
@@ -184,17 +184,18 @@ TestApp::OnProgressChange(nsIWebProgress
                            PRInt32 aMaxTotalProgress)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TestApp::OnLocationChange(nsIWebProgress *aWebProgress,
                            nsIRequest *aRequest,
-                           nsIURI *aLocation)
+                           nsIURI *aLocation,
+                           PRUint32 aFlags)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TestApp::OnStatusChange(nsIWebProgress *aWebProgress,
                          nsIRequest *aRequest,
                          nsresult aStatus,
--- a/xpfe/appshell/src/nsChromeTreeOwner.cpp
+++ b/xpfe/appshell/src/nsChromeTreeOwner.cpp
@@ -530,17 +530,18 @@ nsChromeTreeOwner::OnStateChange(nsIWebP
                                  PRUint32 aProgressStateFlags,
                                  nsresult aStatus)
 {
    return NS_OK;
 }
 
 NS_IMETHODIMP nsChromeTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress,
                                                   nsIRequest* aRequest,
-                                                  nsIURI* aLocation)
+                                                  nsIURI* aLocation,
+                                                  PRUint32 aFlags)
 {
   bool itsForYou = true;
 
   if (aWebProgress) {
     NS_ENSURE_STATE(mXULWindow);
     nsCOMPtr<nsIDOMWindow> progressWin;
     aWebProgress->GetDOMWindow(getter_AddRefs(progressWin));
 
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -590,17 +590,18 @@ nsWebShellWindow::OnStateChange(nsIWebPr
   LoadContentAreas();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebShellWindow::OnLocationChange(nsIWebProgress *aProgress,
                                    nsIRequest *aRequest,
-                                   nsIURI *aURI)
+                                   nsIURI *aURI,
+                                   PRUint32 aFlags)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsWebShellWindow::OnStatusChange(nsIWebProgress* aWebProgress,
                                  nsIRequest* aRequest,