Merge mozilla-central to tracemonkey.
authorRobert Sayre <sayrer@gmail.com>
Mon, 12 Apr 2010 18:11:24 -0400
changeset 40877 1051c470fbbf8360d41c15f216d6d2c391480c1a
parent 40876 c6b51d87e9593064cbdfeafd90c53cd8267242af (current diff)
parent 40724 9614b3d45ff4c3e3bc2b675ccbf80dd29e854e7e (diff)
child 40878 75928f966ea22606e196a3570e91aee848580479
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone1.9.3a5pre
Merge mozilla-central to tracemonkey.
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -376,17 +376,17 @@ nsPrincipal::Subsumes(nsIPrincipal *aOth
 {
   return Equals(aOther, aResult);
 }
 
 static PRBool
 URIIsLocalFile(nsIURI *aURI)
 {
   PRBool isFile;
-  nsCOMPtr<nsINetUtil> util = do_GetIOService();
+  nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
 
   return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
                                 nsIProtocolHandler::URI_IS_LOCAL_FILE,
                                 &isFile)) &&
          isFile;
 }
 
 NS_IMETHODIMP
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -92,16 +92,23 @@
 #include <stdarg.h>
 #ifdef MOZ_SMIL
 #include "nsSMILMappedAttribute.h"
 #include "nsSVGTransformSMILAttr.h"
 #include "nsSVGAnimatedTransformList.h"
 #include "nsIDOMSVGTransformable.h"
 #endif // MOZ_SMIL
 
+// This is needed to ensure correct handling of calls to the
+// vararg-list methods in this file:
+//   nsSVGElement::GetAnimated{Length,Number,Integer}Values
+// See bug 547964 for details:
+PR_STATIC_ASSERT(sizeof(void*) == sizeof(nsnull));
+
+
 nsSVGEnumMapping nsSVGElement::sSVGUnitTypesMap[] = {
   {&nsGkAtoms::userSpaceOnUse, nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE},
   {&nsGkAtoms::objectBoundingBox, nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX},
   {nsnull, 0}
 };
 
 nsSVGElement::nsSVGElement(nsINodeInfo *aNodeInfo)
   : nsSVGElementBase(aNodeInfo), mSuppressNotification(PR_FALSE)
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -10642,17 +10642,17 @@ nsDocShell::URIInheritsSecurityContext(n
                                aResult);
 }
 
 /* static */
 PRBool
 nsDocShell::URIIsLocalFile(nsIURI *aURI)
 {
     PRBool isFile;
-    nsCOMPtr<nsINetUtil> util = do_GetIOService();
+    nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
 
     return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
                                     nsIProtocolHandler::URI_IS_LOCAL_FILE,
                                     &isFile)) &&
            isFile;
 }
 
 /* static */
--- a/dom/plugins/PluginMessageUtils.h
+++ b/dom/plugins/PluginMessageUtils.h
@@ -205,18 +205,20 @@ NPNVariableToString(NPNVariable aVar)
 
     default: return "???";
     }
 }
 #undef VARSTR
 
 inline bool IsPluginThread()
 {
-  MessageLoop::Type type = MessageLoop::current()->type();
-  return type == MessageLoop::TYPE_UI;
+  MessageLoop* loop = MessageLoop::current();
+  if (!loop)
+      return false;
+  return (loop->type() == MessageLoop::TYPE_UI);
 }
 
 inline void AssertPluginThread()
 {
   NS_ASSERTION(IsPluginThread(), "Should be on the plugin's main thread!");
 }
 
 #define ENSURE_PLUGIN_THREAD(retval) \
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -158,16 +158,18 @@ nsEditor::nsEditor()
 ,  mDocWeak(nsnull)
 ,  mPhonetic(nsnull)
 {
   //initialize member variables here
 }
 
 nsEditor::~nsEditor()
 {
+  NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?");
+
   mTxnMgr = nsnull;
 
   delete mPhonetic;
  
   NS_IF_RELEASE(mViewManager);
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsEditor)
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -1081,16 +1081,26 @@ static cairo_status_t
 }
 
 static cairo_status_t
 _cairo_d2d_path_close(void *closure)
 {
     path_conversion *pathConvert =
 	static_cast<path_conversion*>(closure);
 
+    if (!pathConvert->figureActive) {
+	pathConvert->sink->BeginFigure(_d2d_point_from_cairo_point(&pathConvert->current_point),
+				       pathConvert->type);
+	/**
+	 * In this case we mean a single point. For D2D this means we need to add an infinitely
+	 * small line here to get that effect.
+	 */
+	pathConvert->sink->AddLine(_d2d_point_from_cairo_point(&pathConvert->current_point));
+    }
+
     pathConvert->sink->EndFigure(D2D1_FIGURE_END_CLOSED);
     pathConvert->figureActive = false;
     return CAIRO_STATUS_SUCCESS;
 }
 
 /**
  * Create an ID2D1PathGeometry for a cairo_path_fixed_t
  *
@@ -2134,16 +2144,23 @@ cairo_d2d_surface_create_for_hwnd(HWND w
 
     /**
      * Create a swap chain, this swap chain will contain the backbuffer for
      * the window we draw to. The front buffer is the full screen front
      * buffer.
      */
     hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, &newSurf->dxgiChain);
 
+    /**
+     * We do not want DXGI to intercept alt-enter events and make the window go
+     * fullscreen! This shouldn't be in the cairo backend but controlled through
+     * the device. See comments on mozilla bug 553603.
+     */
+    dxgiFactory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES);
+
     if (FAILED(hr)) {
 	goto FAIL_HWND;
     }
     /** Get the backbuffer surface from the swap chain */
     hr = newSurf->dxgiChain->GetBuffer(0,
 	                               IID_PPV_ARGS(&newSurf->backBuf));
 
     if (FAILED(hr)) {
--- a/ipc/chromium/src/base/message_loop.h
+++ b/ipc/chromium/src/base/message_loop.h
@@ -432,16 +432,18 @@ public:
 class MessageLoopForUI : public MessageLoop {
  public:
   MessageLoopForUI(Type type=TYPE_UI) : MessageLoop(type) {
   }
 
   // Returns the MessageLoopForUI of the current thread.
   static MessageLoopForUI* current() {
     MessageLoop* loop = MessageLoop::current();
+    if (!loop)
+      return NULL;
 #ifdef CHROMIUM_MOZILLA_BUILD
     Type type = loop->type();
     DCHECK(type == MessageLoop::TYPE_UI ||
            type == MessageLoop::TYPE_MOZILLA_UI);
 #else
     DCHECK_EQ(MessageLoop::TYPE_UI, loop->type());
 #endif
     return static_cast<MessageLoopForUI*>(loop);
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -217,30 +217,36 @@ GeckoChildProcessHost::PerformAsyncLaunc
 
   childArgv.push_back(exePath.value());
 
   childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end());
 
   childArgv.push_back(pidstring);
   childArgv.push_back(childProcessType);
 
-#if defined(MOZ_CRASHREPORTER) && !defined(XP_MACOSX)
+#if defined(MOZ_CRASHREPORTER)
+#  if defined(OS_LINUX)
   int childCrashFd, childCrashRemapFd;
   if (!CrashReporter::CreateNotificationPipeForChild(
         &childCrashFd, &childCrashRemapFd))
     return false;
   if (0 <= childCrashFd) {
     mFileMap.push_back(std::pair<int,int>(childCrashFd, childCrashRemapFd));
     // "true" == crash reporting enabled
     childArgv.push_back("true");
   }
   else {
     // "false" == crash reporting disabled
     childArgv.push_back("false");
   }
+#  elif defined(XP_MACOSX)
+  // Call the stub for initialization side effects.  Eventually this
+  // code will be unified with that above.
+  CrashReporter::CreateNotificationPipeForChild();
+#  endif  // OS_LINUX
 #endif
 
   base::LaunchApp(childArgv, mFileMap,
 #ifdef OS_LINUX
                   newEnvVars,
 #endif
                   false, &process);
 
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -1018,16 +1018,22 @@ nsTextControlFrame::PreDestroy()
       GetValue(value, PR_TRUE);
 
       mUseEditor = PR_FALSE;
 
       // Next store the frame state in the control
       // (now that mUseEditor is false values get stored
       // in content).
       SetValue(value);
+
+      // Reset mUseEditor for now, so that if any of the rest of the operation
+      // leads to an attempt at getting the editor, lazy initialization doesn't
+      // kick in.  See bug 557689 for an example of the types of problems this
+      // prevents.
+      mUseEditor = PR_TRUE;
     }
     mEditor->PreDestroy(PR_TRUE);
   }
   
   // Clean up the controller
 
   if (!SuppressEventHandlers(PresContext()))
   {
@@ -1059,16 +1065,17 @@ nsTextControlFrame::PreDestroy()
           {
             editController->SetCommandContext(nsnull);
           }
         }
       }
     }
   }
 
+  mUseEditor = PR_FALSE;
   mEditor = nsnull;
   if (mSelCon) {
     mSelCon->SetScrollableFrame(nsnull);
     mSelCon = nsnull;
   }
   if (mFrameSel) {
     mFrameSel->DisconnectFromPresShell();
     mFrameSel = nsnull;
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -1200,16 +1200,21 @@ nsContainerFrame::RemovePropTableFrame(n
 }
 
 nsresult
 nsContainerFrame::SetPropTableFrames(nsPresContext*                 aPresContext,
                                      nsFrameList*                   aFrameList,
                                      const FramePropertyDescriptor* aProperty)
 {
   NS_PRECONDITION(aPresContext && aProperty && aFrameList, "null ptr");
+  NS_PRECONDITION(
+    (aProperty != nsContainerFrame::OverflowContainersProperty() &&
+     aProperty != nsContainerFrame::ExcessOverflowContainersProperty()) ||
+    IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
+    "this type of frame can't have overflow containers");
   aPresContext->PropertyTable()->Set(this, aProperty, aFrameList);
   return NS_OK;
 }
 
 /**
  * Push aFromChild and its next siblings to the next-in-flow. Change the
  * geometric parent of each frame that's pushed. If there is no next-in-flow
  * the frames are placed on the overflow list (and the geometric parent is
--- a/layout/generic/nsPageContentFrame.h
+++ b/layout/generic/nsPageContentFrame.h
@@ -52,16 +52,21 @@ public:
 
   // nsIFrame
   NS_IMETHOD  Reflow(nsPresContext*      aPresContext,
                      nsHTMLReflowMetrics& aDesiredSize,
                      const nsHTMLReflowState& aMaxSize,
                      nsReflowStatus&      aStatus);
 
   virtual PRBool IsContainingBlock() const;
+  virtual PRBool IsFrameOfType(PRUint32 aFlags) const
+  {
+    return ViewportFrame::IsFrameOfType(aFlags &
+             ~(nsIFrame::eCanContainOverflowContainers));
+  }
 
   virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
 
   /**
    *  Computes page size based on shared page data; SetSharedPageData must be
    *  given valid data first.
    */
   virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
--- a/layout/xul/base/src/nsScrollbarButtonFrame.cpp
+++ b/layout/xul/base/src/nsScrollbarButtonFrame.cpp
@@ -69,17 +69,21 @@ NS_NewScrollbarButtonFrame (nsIPresShell
 NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
 
 NS_IMETHODIMP
 nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext, 
                                     nsGUIEvent* aEvent,
                                     nsEventStatus* aEventStatus)
 {  
   NS_ENSURE_ARG_POINTER(aEventStatus);
-  if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
+
+  // If a web page calls event.preventDefault() we still want to
+  // scroll when scroll arrow is clicked. See bug 511075.
+  if (!mContent->IsInNativeAnonymousSubtree() &&
+      nsEventStatus_eConsumeNoDefault == *aEventStatus) {
     return NS_OK;
   }
 
   // XXX hack until handle release is actually called in nsframe.
   if (aEvent->message == NS_MOUSE_EXIT_SYNTH ||
       aEvent->message == NS_MOUSE_BUTTON_UP)
      HandleRelease(aPresContext, aEvent, aEventStatus);
   
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -449,17 +449,21 @@ nsSliderFrame::DoLayout(nsBoxLayoutState
 
 
 NS_IMETHODIMP
 nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
                                       nsGUIEvent* aEvent,
                                       nsEventStatus* aEventStatus)
 {
   NS_ENSURE_ARG_POINTER(aEventStatus);
-  if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
+
+  // If a web page calls event.preventDefault() we still want to
+  // scroll when scroll arrow is clicked. See bug 511075.
+  if (!mContent->IsInNativeAnonymousSubtree() &&
+      nsEventStatus_eConsumeNoDefault == *aEventStatus) {
     return NS_OK;
   }
 
   nsIBox* scrollbarBox = GetScrollbar();
   nsCOMPtr<nsIContent> scrollbar;
   scrollbar = GetContentOfBox(scrollbarBox);
   PRBool isHorizontal = IsHorizontal();
 
--- a/layout/xul/base/test/Makefile.in
+++ b/layout/xul/base/test/Makefile.in
@@ -46,13 +46,14 @@ include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = 	test_bug381167.xhtml \
 		test_bug393970.xul \
 		test_resizer.xul \
 		window_resizer.xul \
 		window_resizer_element.xul \
 		test_bug477754.xul \
 		test_stack.xul \
+		test_bug511075.html \
 		test_splitter.xul \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/layout/xul/base/test/test_bug511075.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=511075
+-->
+<head>
+  <title>Test for Bug 511075</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+  #scroller {
+    border: 1px solid black;
+  }
+  </style>
+</head>
+<body onload="runTests()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=511075">Mozilla Bug 511075</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 511075 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var tests = [
+  function() {
+    ok(true, "Setting location.hash should scroll.");
+    nextTest();
+    // Click the top scroll arrow.
+    var x = scroller.getBoundingClientRect().width - 5;
+    synthesizeMouse(scroller, x, 5, { type : "mousedown" }, window);
+    synthesizeMouse(scroller, x, 5, { type: "mouseup" }, window);
+  },
+  function() {
+    ok(true, "Clicking the top scroll arrow should scroll.");
+    nextTest();
+    // Click the bottom scroll arrow.
+    var x = scroller.getBoundingClientRect().width - 5;
+    var y = scroller.getBoundingClientRect().height - 25;
+    synthesizeMouse(scroller, x, y, { type : "mousedown" }, window);
+    synthesizeMouse(scroller, x, y, { type: "mouseup" }, window);
+  },
+  function() {
+    ok(true, "Clicking the bottom scroll arrow should scroll.");
+    nextTest();
+    // Click the scrollbar.
+    var x = scroller.getBoundingClientRect().width - 5;
+    synthesizeMouse(scroller, x, 40, { type : "mousedown" }, window);
+    synthesizeMouse(scroller, x, 40, { type: "mouseup" }, window);
+  },
+  function() {
+    ok(true, "Clicking the scrollbar should scroll");
+    nextTest();
+    // Click the scrollbar.
+    var x = scroller.getBoundingClientRect().width - 5;
+    var y = scroller.getBoundingClientRect().height - 60;
+    synthesizeMouse(scroller, x, y, { type : "mousedown" }, window);
+    synthesizeMouse(scroller, x, y, { type: "mouseup" }, window);
+  },
+  function() {
+    ok(true, "Clicking the scrollbar should scroll");
+    finish();
+  }
+];
+
+document.onmousedown = function () { return false; };
+document.onmouseup = function () { return true; };
+
+
+var scroller;
+var timer = 0;
+
+function failure() {
+  ok(false, scroller.onscroll + " did not run!");
+  scroller.onscroll = null;
+  finish();
+}
+
+function nextTest() {
+  clearTimeout(timer);
+  scroller.onscroll = tests.shift();
+  timer = setTimeout(failure, 2000);
+}
+
+function runTests() {
+  scroller = document.getElementById("scroller");
+  nextTest();
+  window.location.hash = "initialPosition";
+}
+
+function finish() {
+  document.onmousedown = null;
+  document.onmouseup = null;
+  clearTimeout(timer);
+  window.location.hash = "topPosition";
+  SimpleTest.finish();
+}
+
+
+</script>
+</pre>
+<div id="scroller" style="overflow: scroll; width: 100px; height: 150px;">
+<a id="topPosition" name="topPosition">top</a>
+<div style="width: 20000px; height: 20000px;"></div>
+<a id="initialPosition" name="initialPosition">initialPosition</a>
+<div style="width: 20000px; height: 20000px;"></div>
+</div>
+</body>
+</html>
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
@@ -1431,16 +1431,28 @@ nsresult nsNPAPIPluginInstance::GetCallb
     return NS_ERROR_NULL_POINTER;
 
   return NS_OK;
 }
 
 NPError nsNPAPIPluginInstance::SetWindowless(PRBool aWindowless)
 {
   mWindowless = aWindowless;
+
+  if (mMIMEType) {
+      // bug 558434 - Prior to 3.6.4, we assumed windowless was transparent.
+      // Silverlight apparently relied on this quirk, so we default to
+      // transparent unless they specify otherwise after setting the windowless
+      // property. (Last tested version: sl 3.0). 
+      NS_NAMED_LITERAL_CSTRING(silverlight, "application/x-silverlight");
+      if (!PL_strncasecmp(mMIMEType, silverlight.get(), silverlight.Length())) {
+          mTransparent = PR_TRUE;
+      }
+  }
+
   return NPERR_NO_ERROR;
 }
 
 NPError nsNPAPIPluginInstance::SetWindowlessLocal(PRBool aWindowlessLocal)
 {
   mWindowlessLocal = aWindowlessLocal;
   return NPERR_NO_ERROR;
 }
--- a/modules/plugin/base/src/nsPluginHost.cpp
+++ b/modules/plugin/base/src/nsPluginHost.cpp
@@ -396,17 +396,17 @@ public:
                       nsIPluginInstance *aInstance,
                       nsIPluginStreamListener *aListener,
                       PRInt32 requestCount = 1);
 
   nsresult InitializeEmbedded(nsIURI *aURL,
                              nsIPluginInstance* aInstance,
                              nsIPluginInstanceOwner *aOwner = nsnull);
 
-  nsresult InitializeFullPage(nsIPluginInstance *aInstance);
+  nsresult InitializeFullPage(nsIURI* aURL, nsIPluginInstance *aInstance);
 
   nsresult OnFileAvailable(nsIFile* aFile);
 
   nsresult ServeStreamAsFile(nsIRequest *request, nsISupports *ctxt);
   
   nsIPluginInstance *GetPluginInstance() { return mInstance; }
 
 private:
@@ -808,24 +808,26 @@ nsresult nsPluginStreamListenerPeer::Ini
   if (!mDataForwardToRequest)
       return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 
 // Called by NewFullPagePluginStream()
-nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIPluginInstance *aInstance)
+nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIURI* aURL, nsIPluginInstance *aInstance)
 {
   PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   ("nsPluginStreamListenerPeer::InitializeFullPage instance=%p\n",aInstance));
 
   NS_ASSERTION(mInstance == nsnull, "nsPluginStreamListenerPeer::InitializeFullPage mInstance != nsnull");
   mInstance = aInstance;
 
+  mURL = aURL;
+
   mDataForwardToRequest = new nsHashtable(16, PR_FALSE);
   if (!mDataForwardToRequest)
       return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 // SetupPluginCacheFile is called if we have to save the stream to disk.
@@ -2353,17 +2355,17 @@ NS_IMETHODIMP nsPluginHost::InstantiateF
   if (FindStoppedPluginForURL(aURI, aOwner) == NS_OK) {
     PLUGIN_LOG(PLUGIN_LOG_NOISY,
     ("nsPluginHost::InstantiateFullPagePlugin FoundStopped mime=%s\n",aMimeType));
 
     nsIPluginInstance* instance;
     aOwner->GetInstance(instance);
     nsPluginTag* pluginTag = FindPluginForType(aMimeType, PR_TRUE);
     if (!pluginTag || !pluginTag->mIsJavaPlugin)
-      NewFullPagePluginStream(aStreamListener, instance);
+      NewFullPagePluginStream(aStreamListener, aURI, instance);
     NS_IF_RELEASE(instance);
     return NS_OK;
   }
 
   nsresult rv = SetUpPluginInstance(aMimeType, aURI, aOwner);
 
   if (NS_OK == rv) {
     nsCOMPtr<nsIPluginInstance> instance;
@@ -2376,17 +2378,17 @@ NS_IMETHODIMP nsPluginHost::InstantiateF
       instance->Start();
       aOwner->CreateWidget();
 
       // If we've got a native window, the let the plugin know about it.
       nsPluginNativeWindow * window = (nsPluginNativeWindow *)win;
       if (window->window)
         window->CallSetWindow(instance);
 
-      rv = NewFullPagePluginStream(aStreamListener, instance);
+      rv = NewFullPagePluginStream(aStreamListener, aURI, instance);
 
       // If we've got a native window, the let the plugin know about it.
       if (window->window)
         window->CallSetWindow(instance);
     }
   }
 
   PLUGIN_LOG(PLUGIN_LOG_NORMAL,
@@ -4519,25 +4521,26 @@ nsresult nsPluginHost::NewEmbeddedPlugin
     }
   }
 
   return rv;
 }
 
 // Called by InstantiateFullPagePlugin()
 nsresult nsPluginHost::NewFullPagePluginStream(nsIStreamListener *&aStreamListener,
+                                               nsIURI* aURI,
                                                nsIPluginInstance *aInstance)
 {
   nsPluginStreamListenerPeer  *listener = new nsPluginStreamListenerPeer();
   if (!listener)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsresult rv;
 
-  rv = listener->InitializeFullPage(aInstance);
+  rv = listener->InitializeFullPage(aURI, aInstance);
 
   aStreamListener = listener;
   NS_ADDREF(listener);
 
   // add peer to list of stream peers for this instance
   nsPluginInstanceTag * p = FindInstanceTag(aInstance);
   if (p)
     p->mStreams.AppendObject(listener);
--- a/modules/plugin/base/src/nsPluginHost.h
+++ b/modules/plugin/base/src/nsPluginHost.h
@@ -187,17 +187,17 @@ private:
   NewEmbeddedPluginStreamListener(nsIURI* aURL, nsIPluginInstanceOwner *aOwner,
                                   nsIPluginInstance* aInstance,
                                   nsIStreamListener** aListener);
 
   nsresult
   NewEmbeddedPluginStream(nsIURI* aURL, nsIPluginInstanceOwner *aOwner, nsIPluginInstance* aInstance);
 
   nsresult
-  NewFullPagePluginStream(nsIStreamListener *&aStreamListener, nsIPluginInstance *aInstance);
+  NewFullPagePluginStream(nsIStreamListener *&aStreamListener, nsIURI* aURI, nsIPluginInstance *aInstance);
 
   // Return an nsPluginTag for this type, if any.  If aCheckEnabled is
   // true, only enabled plugins will be returned.
   nsPluginTag*
   FindPluginForType(const char* aMimeType, PRBool aCheckEnabled);
 
   nsPluginTag*
   FindPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
--- a/modules/plugin/test/mochitest/Makefile.in
+++ b/modules/plugin/test/mochitest/Makefile.in
@@ -63,16 +63,19 @@ include $(topsrcdir)/config/rules.mk
   test_pluginstream_geturl.html \
   test_pluginstream_geturlnotify.html \
   test_pluginstream_asfile.html \
   test_pluginstream_asfileonly.html \
   test_pluginstream_post.html \
   test_pluginstream_poststream.html \
   test_pluginstream_seek.html \
   test_pluginstream_newstream.html \
+  test_fullpage.html \
+  loremipsum.xtest \
+  loremipsum.xtest^headers^ \
   test_multipleinstanceobjects.html \
   test_streamNotify.html \
   test_instantiation.html \
   test_cookies.html \
   test_npn_timers.html \
   test_npn_asynccall.html \
   test_bug532208.html \
   large-pic.jpg \
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/loremipsum.xtest
@@ -0,0 +1,11 @@
+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut laboreet dolore magna aliquyam erat.
+
+Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/loremipsum.xtest^headers^
@@ -0,0 +1,1 @@
+Content-Type: application/x-test
new file mode 100644
--- /dev/null
+++ b/modules/plugin/test/mochitest/test_fullpage.html
@@ -0,0 +1,35 @@
+<head>
+  <title>Full-page seekable stream</title>
+
+  <script type="text/javascript"
+          src="/MochiKit/packed.js"></script>
+  <script type="text/javascript"
+          src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css"
+        href="/tests/SimpleTest/test.css">
+
+<body>
+  <p id="display"></p>
+
+  <iframe src="loremipsum.xtest" streamtype="seek"></iframe>
+  <iframe id="testframe" name="testframe" onload="frameLoaded()"></iframe>
+
+  <script type="application/javascript">
+    SimpleTest.waitForExplicitFinish();
+
+    function frameLoaded() {
+      var testframe = document.getElementById('testframe');
+      var content = testframe.contentDocument.body.innerHTML;
+      if (!content.length)
+        return;
+
+      var req = new XMLHttpRequest();
+      req.open('GET', 'loremipsum.xtest', false);
+      req.overrideMimeType('text/plain; charset=x-user-defined');
+      req.send(null);
+      is(req.status, 200, "bad XMLHttpRequest");
+      is(content, req.responseText.replace(/\r\n/g, "\n"),
+         "content doesn't match");
+      SimpleTest.finish();
+    }
+  </script>
--- a/modules/plugin/test/testplugin/README
+++ b/modules/plugin/test/testplugin/README
@@ -293,16 +293,20 @@ The attributes which control stream test
 "functiontofail": one of "npp_newstream", "npp_write", "npp_destroystream".
   When specified, the given function will return an error code (-1 for
   NPP_Write, or else the value of the "failurecode" attribute) the first time
   it is called by the browser.
 
 "failurecode": one of the NPError constants.  Used to specify the error
   that will be returned by the "functiontofail".
 
+If the plugin is instantiated as a full-page plugin, the following defaults
+are used:
+  streammode="seek" frame="testframe" range="100,100"
+
 The .streamTest(url, doPost, postData, callback) function will test how
 NPN_GetURLNotify and NPN_PostURLNotify behave when they are called with
 arbitrary (malformed) URLs. The function will return `true` if NPN_GetURLNotify
 succeeds, and `false` if it fails.
 @param doPost whether to call NPN_PostURLNotify
 @param postData null, or a string to send a postdata
 @callback which will be called when the urlnotify is received with the notify
 result
--- a/modules/plugin/test/testplugin/nptest.cpp
+++ b/modules/plugin/test/testplugin/nptest.cpp
@@ -669,17 +669,23 @@ NPP_New(NPMIMEType pluginType, NPP insta
     return NPERR_GENERIC_ERROR;
   }
   scriptableObject->npp = instance;
   scriptableObject->drawMode = DM_DEFAULT;
   scriptableObject->drawColor = 0;
   instanceData->scriptableObject = scriptableObject;
 
   instanceData->instanceCountWatchGeneration = sCurrentInstanceCountWatchGeneration;
-  
+
+  if (NP_FULL == mode) {
+    instanceData->streamMode = NP_SEEK;
+    instanceData->frame = "testframe";
+    addRange(instanceData, "100,100");
+  }
+
   bool requestWindow = false;
   // handle extra params
   for (int i = 0; i < argc; i++) {
     if (strcmp(argn[i], "drawmode") == 0) {
       if (strcmp(argv[i], "solid") == 0)
         scriptableObject->drawMode = DM_SOLID_COLOR;    
     }
     else if (strcmp(argn[i], "color") == 0) {
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -18,16 +18,17 @@
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Bradley Baetz <bbaetz@student.usyd.edu.au>
  *   Malcolm Smith <malsmith@cs.rmit.edu.au>
+ *   Taras Glek <tglek@mozilla.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
@@ -96,24 +97,57 @@
 #include "nsServiceManagerUtils.h"
 #include "nsINestedURI.h"
 #include "nsIMutable.h"
 #include "nsIPropertyBag2.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsIIDNService.h"
 #include "nsIChannelEventSink.h"
 #include "nsIChannelPolicy.h"
+#include "mozilla/Services.h"
 
+#ifdef MOZILLA_INTERNAL_API
+
+inline already_AddRefed<nsIIOService>
+do_GetIOService(nsresult* error = 0)
+{
+    already_AddRefed<nsIIOService> ret = mozilla::services::GetIOService();
+    if (error)
+        *error = ret.get() ? NS_OK : NS_ERROR_FAILURE;
+    return ret;
+}
+
+inline already_AddRefed<nsINetUtil>
+do_GetNetUtil(nsresult *error = 0) 
+{
+    nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
+    already_AddRefed<nsINetUtil> ret = nsnull;
+    if (io)
+        CallQueryInterface(io, &ret.mRawPtr);
+
+    if (error)
+        *error = ret.get() ? NS_OK : NS_ERROR_FAILURE;
+    return ret;
+}
+#else
 // Helper, to simplify getting the I/O service.
 inline const nsGetServiceByContractIDWithError
 do_GetIOService(nsresult* error = 0)
 {
     return nsGetServiceByContractIDWithError(NS_IOSERVICE_CONTRACTID, error);
 }
 
+// An alias to do_GetIOService
+inline const nsGetServiceByContractIDWithError
+do_GetNetUtil(nsresult* error = 0)
+{
+    return do_GetIOService(error);
+}
+#endif
+
 // private little helper function... don't call this directly!
 inline nsresult
 net_EnsureIOService(nsIIOService **ios, nsCOMPtr<nsIIOService> &grip)
 {
     nsresult rv = NS_OK;
     if (!*ios) {
         grip = do_GetIOService(&rv);
         *ios = grip;
@@ -873,17 +907,17 @@ NS_ExamineForProxy(const char    *scheme
 
 inline nsresult
 NS_ParseContentType(const nsACString &rawContentType,
                     nsCString        &contentType,
                     nsCString        &contentCharset)
 {
     // contentCharset is left untouched if not present in rawContentType
     nsresult rv;
-    nsCOMPtr<nsINetUtil> util = do_GetIOService(&rv);
+    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCString charset;
     PRBool hadCharset;
     rv = util->ParseContentType(rawContentType, charset, &hadCharset,
                                 contentType);
     if (NS_SUCCEEDED(rv) && hadCharset)
         contentCharset = charset;
     return rv;
@@ -893,17 +927,17 @@ inline nsresult
 NS_ExtractCharsetFromContentType(const nsACString &rawContentType,
                                  nsCString        &contentCharset,
                                  PRBool           *hadCharset,
                                  PRInt32          *charsetStart,
                                  PRInt32          *charsetEnd)
 {
     // contentCharset is left untouched if not present in rawContentType
     nsresult rv;
-    nsCOMPtr<nsINetUtil> util = do_GetIOService(&rv);
+    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return util->ExtractCharsetFromContentType(rawContentType,
                                                contentCharset,
                                                charsetStart,
                                                charsetEnd,
                                                hadCharset);
 }
@@ -1426,20 +1460,21 @@ NS_TryToSetImmutable(nsIURI* uri)
  * the input URI.  The optional second arg indicates whether we had to fall
  * back to the input URI.  Passing in a null URI is ok.
  */
 inline already_AddRefed<nsIURI>
 NS_TryToMakeImmutable(nsIURI* uri,
                       nsresult* outRv = nsnull)
 {
     nsresult rv;
-    nsCOMPtr<nsINetUtil> util = do_GetIOService(&rv);
+    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
+
     nsIURI* result = nsnull;
     if (NS_SUCCEEDED(rv)) {
-        NS_ASSERTION(util, "do_GetIOService lied");
+        NS_ASSERTION(util, "do_GetNetUtil lied");
         rv = util->ToImmutableURI(uri, &result);
     }
 
     if (NS_FAILED(rv)) {
         NS_IF_ADDREF(result = uri);
     }
 
     if (outRv) {
@@ -1454,17 +1489,17 @@ NS_TryToMakeImmutable(nsIURI* uri,
  * inner URIs, has all the given protocol flags.
  */
 inline nsresult
 NS_URIChainHasFlags(nsIURI   *uri,
                     PRUint32  flags,
                     PRBool   *result)
 {
     nsresult rv;
-    nsCOMPtr<nsINetUtil> util = do_GetIOService(&rv);
+    nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return util->URIChainHasFlags(uri, flags, result);
 }
 
 /**
  * Helper function for getting the innermost URI for a given URI.  The return
  * value could be just the object passed in if it's not a nested URI.
--- a/toolkit/content/Services.jsm
+++ b/toolkit/content/Services.jsm
@@ -107,8 +107,12 @@ XPCOMUtils.defineLazyServiceGetter(Servi
 
 XPCOMUtils.defineLazyServiceGetter(Services, "tm",
                                    "@mozilla.org/thread-manager;1",
                                    "nsIThreadManager");
 
 XPCOMUtils.defineLazyServiceGetter(Services, "console",
                                    "@mozilla.org/consoleservice;1",
                                    "nsIConsoleService");
+
+XPCOMUtils.defineLazyServiceGetter(Services, "strings",
+                                   "@mozilla.org/intl/stringbundle;1",
+                                   "nsIStringBundleService");
--- a/toolkit/content/tests/browser/browser_Services.js
+++ b/toolkit/content/tests/browser/browser_Services.js
@@ -59,9 +59,10 @@ function checkServices() {
   checkService("prompt", Ci.nsIPromptService);
   checkService("search", Ci.nsIBrowserSearchService);
   checkService("storage", Ci.mozIStorageService);
   checkService("vc", Ci.nsIVersionComparator);
   checkService("locale", Ci.nsILocaleService);
   checkService("scriptloader", Ci.mozIJSSubScriptLoader);
   checkService("ww", Ci.nsIWindowWatcher);
   checkService("tm", Ci.nsIThreadManager);
+  checkService("strings", Ci.nsIStringBundleService);
 }
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -1429,21 +1429,17 @@ OnChildProcessDumpRequested(void* aConte
     pidToMinidump->Put(pid, minidump);
   }
 }
 #endif  // XP_MACOSX
 
 static bool
 OOPInitialized()
 {
-#if defined(XP_MACOSX)
-  return true;
-#else
-  return crashServer != NULL;
-#endif
+  return pidToMinidump != NULL;
 }
 
 static void
 OOPInit()
 {
   NS_ABORT_IF_FALSE(!OOPInitialized(),
                     "OOP crash reporter initialized more than once!");
   NS_ABORT_IF_FALSE(gExceptionHandler != NULL,
@@ -1587,16 +1583,24 @@ SetRemoteExceptionHandler()
                      NULL,    // no callback context
                      true,    // install signal handlers
                      kMagicChildCrashReportFd);
 
   // we either do remote or nothing, no fallback to regular crash reporting
   return gExceptionHandler->IsOutOfProcess();
 }
 
+//--------------------------------------------------
+#elif defined(XP_MACOSX)
+void
+CreateNotificationPipeForChild()
+{
+  if (GetEnabled() && !OOPInitialized())
+    OOPInit();
+}
 #endif  // XP_WIN
 
 
 bool
 TakeMinidumpForChild(PRUint32 childPid, nsILocalFile** dump)
 {
   if (!GetEnabled())
     return false;
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -140,15 +140,21 @@ bool SetRemoteExceptionHandler(const nsA
 // the server at |childCrashRemapFd|.  Return true iff successful.
 //
 // If crash reporting is disabled, both outparams will be set to -1
 // and |true| will be returned.
 bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd);
 
 // Child-side API
 bool SetRemoteExceptionHandler();
+
+#  elif defined(XP_MACOSX)
+// When OOP crash reporting is implemented for Mac, it will almost
+// certainly use the same interface as the linux code above.  Until
+// then, we provide stubs.
+void CreateNotificationPipeForChild();
 #endif  // XP_WIN32
 
 bool UnsetRemoteExceptionHandler();
 #endif // MOZ_IPC
 }
 
 #endif /* nsExceptionHandler_h__ */
--- a/xpcom/base/nscore.h
+++ b/xpcom/base/nscore.h
@@ -364,19 +364,25 @@ typedef PRUint32 nsresult;
  */
 #if defined(XP_WIN) && PR_BYTES_PER_LONG == 4
 typedef unsigned long nsrefcnt;
 #else
 typedef PRUint32 nsrefcnt;
 #endif
 
 /**
- * The preferred symbol for null.
+ * The preferred symbol for null.  Make sure this is the same size as
+ * void* on the target.  See bug 547964.
  */
-#define nsnull 0
+#if defined(_WIN64)
+# define nsnull 0LL
+#else
+# define nsnull 0L
+#endif
+
 
 #include "nsError.h"
 
 /* ------------------------------------------------------------------------ */
 /* Casting macros for hiding C++ features from older compilers */
 
   /*
     All our compiler support template specialization, but not all support the
--- a/xpcom/build/Makefile.in
+++ b/xpcom/build/Makefile.in
@@ -63,16 +63,17 @@ CSRCS		= \
 		$(XPCOM_GLUE_SRC_LCSRCS) \
 		$(NULL)
 
 CPPSRCS		= \
 		$(XPCOM_GLUE_SRC_LCPPSRCS) \
 		$(XPCOM_GLUENS_SRC_LCPPSRCS) \
 		nsXPComInit.cpp \
 		nsXPCOMStrings.cpp \
+		Services.cpp \
 		$(NULL)
 
 ifndef MOZ_ENABLE_LIBXUL
 ifeq (,$(filter-out WINNT WINCE OS2,$(OS_ARCH)))
 CPPSRCS += dlldeps.cpp
 endif
 endif
 
@@ -120,16 +121,18 @@ SDK_HEADERS =  \
 EXPORTS	= \
   nsXPCOMCIDInternal.h \
   xrecore.h \
   nsXULAppAPI.h \
   $(NULL)
 
 EXPORTS_mozilla = \
   XPCOM.h \
+  Services.h \
+  ServiceList.h \
   $(NULL)
 
 # Force use of PIC
 FORCE_USE_PIC	= 1 
 
 ifndef MOZ_ENABLE_LIBXUL
 FORCE_SHARED_LIB = 1
 endif
new file mode 100644
--- /dev/null
+++ b/xpcom/build/ServiceList.h
@@ -0,0 +1,2 @@
+MOZ_SERVICE(IOService, nsIIOService, "@mozilla.org/network/io-service;1")
+MOZ_SERVICE(ObserverService, nsIObserverService, "@mozilla.org/observer-service;1")
new file mode 100644
--- /dev/null
+++ b/xpcom/build/Services.cpp
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** 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 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):
+ *   Taras Glek <tglek@mozilla.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 "mozilla/Services.h"
+#include "nsComponentManager.h"
+#include "nsIIOService.h"
+#include "nsIDirectoryService.h"
+#include "nsIChromeRegistry.h"
+#include "nsIObserverService.h"
+#include "nsNetCID.h"
+#include "nsObserverService.h"
+#include "nsXPCOMPrivate.h"
+
+using namespace mozilla::services;
+
+/*
+ * Define a global variable and a getter for every service in ServiceList.
+ * eg. gIOService and GetIOService()
+ */
+#define MOZ_SERVICE(NAME, TYPE, CONTRACT_ID)                            \
+  static TYPE* g##NAME = nsnull;                                        \
+                                                                        \
+  NS_COM already_AddRefed<TYPE>                                         \
+  mozilla::services::Get##NAME()                                        \
+  {                                                                     \
+    if (!g##NAME) {                                                     \
+      nsCOMPtr<TYPE> os = do_GetService(CONTRACT_ID);                   \
+      g##NAME = os.forget().get();                                      \
+    }                                                                   \
+    NS_IF_ADDREF(g##NAME);                                              \
+    return g##NAME;                                                     \
+  }
+
+#include "ServiceList.h"
+#undef MOZ_SERVICE
+
+/**
+ * Clears service cache, sets gXPCOMShuttingDown
+ */
+void 
+mozilla::services::Shutdown()
+{
+  gXPCOMShuttingDown = PR_TRUE;
+#define MOZ_SERVICE(NAME, TYPE, CONTRACT_ID) NS_IF_RELEASE(g##NAME);
+#include "ServiceList.h"
+#undef MOZ_SERVICE
+}
new file mode 100644
--- /dev/null
+++ b/xpcom/build/Services.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** 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 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):
+ *   Taras Glek <tglek@mozilla.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 ***** */
+
+#ifndef mozilla_Services_h
+#define mozilla_Services_h
+
+#include "nscore.h"
+#include "nsCOMPtr.h"
+
+#define MOZ_SERVICE(NAME, TYPE, SERVICE_CID) class TYPE;
+#include "ServiceList.h"
+#undef MOZ_SERVICE
+
+namespace mozilla {
+namespace services {
+
+#define MOZ_SERVICE(NAME, TYPE, SERVICE_CID) NS_COM already_AddRefed<TYPE> Get##NAME();
+#include "ServiceList.h"
+#undef MOZ_SERVICE
+
+} // namespace services
+} // namespace mozilla
+
+#endif
--- a/xpcom/build/nsXPCOMPrivate.h
+++ b/xpcom/build/nsXPCOMPrivate.h
@@ -306,9 +306,22 @@ void LogTerm();
 #define MAXPATHLEN _MAX_PATH
 #elif defined(CCHMAXPATH)
 #define MAXPATHLEN CCHMAXPATH
 #else
 #define MAXPATHLEN 1024
 #endif
 #endif
 
+extern PRBool gXPCOMShuttingDown;
+
+namespace mozilla {
+namespace services {
+
+/** 
+ * Clears service cache, sets gXPCOMShuttingDown
+ */
+void Shutdown();
+
+} // namespace services
+} // namespace mozilla
+
 #endif
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -137,16 +137,17 @@ NS_DECL_CLASSINFO(nsStringInputStream)
 #ifdef XP_MACOSX
 #include "nsMacUtilsImpl.h"
 #endif
 
 #include "nsSystemInfo.h"
 #include "nsMemoryReporterManager.h"
 
 #include <locale.h>
+#include "mozilla/Services.h"
 
 #ifdef MOZ_IPC
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
 
 #include "mozilla/ipc/BrowserProcessSubThread.h"
 
@@ -797,17 +798,17 @@ ShutdownXPCOM(nsIServiceManager* servMgr
 
             observerService->Shutdown();
         }
     }
 
     // XPCOM is officially in shutdown mode NOW
     // Set this only after the observers have been notified as this
     // will cause servicemanager to become inaccessible.
-    gXPCOMShuttingDown = PR_TRUE;
+    mozilla::services::Shutdown();
 
 #ifdef DEBUG_dougt
     fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n");
 #endif
     // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
     // here again:
     NS_IF_RELEASE(servMgr);
 
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -149,19 +149,16 @@ static const char gIDFormat[] =
     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
 }
 
 NS_DEFINE_CID(kEmptyCID, NS_EMPTY_IID);
 NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
 
 #define UID_STRING_LENGTH 39
 
-// Set to true from NS_ShutdownXPCOM.
-extern PRBool gXPCOMShuttingDown;
-
 static void GetIDString(const nsID& aCID, char buf[UID_STRING_LENGTH])
 {
     PR_snprintf(buf, UID_STRING_LENGTH, gIDFormat,
                 aCID.m0, (PRUint32) aCID.m1, (PRUint32) aCID.m2,
                 (PRUint32) aCID.m3[0], (PRUint32) aCID.m3[1],
                 (PRUint32) aCID.m3[2], (PRUint32) aCID.m3[3],
                 (PRUint32) aCID.m3[4], (PRUint32) aCID.m3[5],
                 (PRUint32) aCID.m3[6], (PRUint32) aCID.m3[7]);