LCOV - code coverage report
Current view: directory - content/base/src - nsObjectLoadingContent.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 940 2 0.2 %
Date: 2012-06-02 Functions: 90 2 2.2 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : // vim:set et cin sw=2 sts=2:
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla <object> loading code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Christian Biesinger <cbiesinger@web.de>.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Justin Dolske <dolske@mozilla.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : /*
      41                 :  * A base class implementing nsIObjectLoadingContent for use by
      42                 :  * various content nodes that want to provide plugin/document/image
      43                 :  * loading functionality (eg <embed>, <object>, <applet>, etc).
      44                 :  */
      45                 : 
      46                 : // Interface headers
      47                 : #include "imgILoader.h"
      48                 : #include "nsEventDispatcher.h"
      49                 : #include "nsIContent.h"
      50                 : #include "nsIDocShell.h"
      51                 : #include "nsIDocument.h"
      52                 : #include "nsIDOMDataContainerEvent.h"
      53                 : #include "nsIDOMDocument.h"
      54                 : #include "nsIDOMEventTarget.h"
      55                 : #include "nsIExternalProtocolHandler.h"
      56                 : #include "nsEventStates.h"
      57                 : #include "nsIObjectFrame.h"
      58                 : #include "nsIPluginDocument.h"
      59                 : #include "nsPluginHost.h"
      60                 : #include "nsIPresShell.h"
      61                 : #include "nsIPrivateDOMEvent.h"
      62                 : #include "nsIScriptGlobalObject.h"
      63                 : #include "nsIScriptSecurityManager.h"
      64                 : #include "nsIStreamConverterService.h"
      65                 : #include "nsIURILoader.h"
      66                 : #include "nsIURL.h"
      67                 : #include "nsIWebNavigation.h"
      68                 : #include "nsIWebNavigationInfo.h"
      69                 : #include "nsIScriptChannel.h"
      70                 : #include "nsIBlocklistService.h"
      71                 : #include "nsIAsyncVerifyRedirectCallback.h"
      72                 : #include "nsIAppShell.h"
      73                 : 
      74                 : #include "nsPluginError.h"
      75                 : 
      76                 : // Util headers
      77                 : #include "prlog.h"
      78                 : 
      79                 : #include "nsAutoPtr.h"
      80                 : #include "nsCURILoader.h"
      81                 : #include "nsContentPolicyUtils.h"
      82                 : #include "nsContentUtils.h"
      83                 : #include "nsDocShellCID.h"
      84                 : #include "nsGkAtoms.h"
      85                 : #include "nsThreadUtils.h"
      86                 : #include "nsNetUtil.h"
      87                 : #include "nsMimeTypes.h"
      88                 : #include "nsStyleUtil.h"
      89                 : #include "nsGUIEvent.h"
      90                 : #include "nsUnicharUtils.h"
      91                 : 
      92                 : // Concrete classes
      93                 : #include "nsFrameLoader.h"
      94                 : 
      95                 : #include "nsObjectLoadingContent.h"
      96                 : #include "mozAutoDocUpdate.h"
      97                 : #include "nsIContentSecurityPolicy.h"
      98                 : #include "nsIChannelPolicy.h"
      99                 : #include "nsChannelPolicy.h"
     100                 : #include "mozilla/dom/Element.h"
     101                 : #include "sampler.h"
     102                 : #include "nsObjectFrame.h"
     103                 : #include "nsDOMClassInfo.h"
     104                 : 
     105                 : #include "nsWidgetsCID.h"
     106                 : #include "nsContentCID.h"
     107                 : static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
     108                 : 
     109                 : #ifdef PR_LOGGING
     110            1464 : static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
     111                 : #endif
     112                 : 
     113                 : #define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
     114                 : #define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
     115                 : 
     116                 : #include "mozilla/Preferences.h"
     117                 : 
     118                 : class nsAsyncInstantiateEvent : public nsRunnable {
     119                 : public:
     120                 :   nsObjectLoadingContent *mContent;
     121               0 :   nsAsyncInstantiateEvent(nsObjectLoadingContent* aContent)
     122               0 :   : mContent(aContent)
     123                 :   {
     124               0 :     static_cast<nsIObjectLoadingContent *>(mContent)->AddRef();
     125               0 :   }
     126                 : 
     127               0 :   ~nsAsyncInstantiateEvent()
     128               0 :   {
     129               0 :     static_cast<nsIObjectLoadingContent *>(mContent)->Release();
     130               0 :   }
     131                 : 
     132                 :   NS_IMETHOD Run();
     133                 : };
     134                 : 
     135                 : NS_IMETHODIMP
     136               0 : nsAsyncInstantiateEvent::Run()
     137                 : {
     138                 :   // do nothing if we've been revoked
     139               0 :   if (mContent->mPendingInstantiateEvent != this) {
     140               0 :     return NS_OK;
     141                 :   }
     142               0 :   mContent->mPendingInstantiateEvent = nsnull;
     143                 : 
     144               0 :   return mContent->SyncStartPluginInstance();
     145                 : }
     146                 : 
     147                 : // Checks to see if the content for a plugin instance has a parent.
     148                 : // The plugin instance is stopped if there is no parent.
     149                 : class InDocCheckEvent : public nsRunnable {
     150                 : public:
     151                 :   nsCOMPtr<nsIContent> mContent;
     152                 : 
     153               0 :   InDocCheckEvent(nsIContent* aContent)
     154               0 :   : mContent(aContent)
     155                 :   {
     156               0 :   }
     157                 : 
     158               0 :   ~InDocCheckEvent()
     159               0 :   {
     160               0 :   }
     161                 : 
     162                 :   NS_IMETHOD Run();
     163                 : };
     164                 : 
     165                 : NS_IMETHODIMP
     166               0 : InDocCheckEvent::Run()
     167                 : {
     168               0 :   if (!mContent->IsInDoc()) {
     169               0 :     nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(mContent);
     170               0 :     if (olc) {
     171               0 :       olc->StopPluginInstance();
     172                 :     }
     173                 :   }
     174               0 :   return NS_OK;
     175                 : }
     176                 : 
     177                 : /**
     178                 :  * A task for firing PluginNotFound and PluginBlocklisted DOM Events.
     179                 :  */
     180                 : class nsPluginErrorEvent : public nsRunnable {
     181                 : public:
     182                 :   nsCOMPtr<nsIContent> mContent;
     183                 :   PluginSupportState mState;
     184                 : 
     185               0 :   nsPluginErrorEvent(nsIContent* aContent, PluginSupportState aState)
     186                 :     : mContent(aContent),
     187               0 :       mState(aState)
     188               0 :   {}
     189                 : 
     190               0 :   ~nsPluginErrorEvent() {}
     191                 : 
     192                 :   NS_IMETHOD Run();
     193                 : };
     194                 : 
     195                 : NS_IMETHODIMP
     196               0 : nsPluginErrorEvent::Run()
     197                 : {
     198               0 :   LOG(("OBJLC []: Firing plugin not found event for content %p\n",
     199                 :        mContent.get()));
     200               0 :   nsString type;
     201               0 :   switch (mState) {
     202                 :     case ePluginClickToPlay:
     203               0 :       type = NS_LITERAL_STRING("PluginClickToPlay");
     204               0 :       break;
     205                 :     case ePluginUnsupported:
     206               0 :       type = NS_LITERAL_STRING("PluginNotFound");
     207               0 :       break;
     208                 :     case ePluginDisabled:
     209               0 :       type = NS_LITERAL_STRING("PluginDisabled");
     210               0 :       break;
     211                 :     case ePluginBlocklisted:
     212               0 :       type = NS_LITERAL_STRING("PluginBlocklisted");
     213               0 :       break;
     214                 :     case ePluginOutdated:
     215               0 :       type = NS_LITERAL_STRING("PluginOutdated");
     216               0 :       break;
     217                 :     default:
     218               0 :       return NS_OK;
     219                 :   }
     220                 :   nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
     221               0 :                                        type, true, true);
     222                 : 
     223               0 :   return NS_OK;
     224                 : }
     225                 : 
     226                 : /**
     227                 :  * A task for firing PluginCrashed DOM Events.
     228                 :  */
     229                 : class nsPluginCrashedEvent : public nsRunnable {
     230                 : public:
     231                 :   nsCOMPtr<nsIContent> mContent;
     232                 :   nsString mPluginDumpID;
     233                 :   nsString mBrowserDumpID;
     234                 :   nsString mPluginName;
     235                 :   nsString mPluginFilename;
     236                 :   bool mSubmittedCrashReport;
     237                 : 
     238               0 :   nsPluginCrashedEvent(nsIContent* aContent,
     239                 :                        const nsAString& aPluginDumpID,
     240                 :                        const nsAString& aBrowserDumpID,
     241                 :                        const nsAString& aPluginName,
     242                 :                        const nsAString& aPluginFilename,
     243                 :                        bool submittedCrashReport)
     244                 :     : mContent(aContent),
     245                 :       mPluginDumpID(aPluginDumpID),
     246                 :       mBrowserDumpID(aBrowserDumpID),
     247                 :       mPluginName(aPluginName),
     248                 :       mPluginFilename(aPluginFilename),
     249               0 :       mSubmittedCrashReport(submittedCrashReport)
     250               0 :   {}
     251                 : 
     252               0 :   ~nsPluginCrashedEvent() {}
     253                 : 
     254                 :   NS_IMETHOD Run();
     255                 : };
     256                 : 
     257                 : NS_IMETHODIMP
     258               0 : nsPluginCrashedEvent::Run()
     259                 : {
     260               0 :   LOG(("OBJLC []: Firing plugin crashed event for content %p\n",
     261                 :        mContent.get()));
     262                 : 
     263                 :   nsCOMPtr<nsIDOMDocument> domDoc =
     264               0 :     do_QueryInterface(mContent->GetDocument());
     265               0 :   if (!domDoc) {
     266               0 :     NS_WARNING("Couldn't get document for PluginCrashed event!");
     267               0 :     return NS_OK;
     268                 :   }
     269                 : 
     270               0 :   nsCOMPtr<nsIDOMEvent> event;
     271               0 :   domDoc->CreateEvent(NS_LITERAL_STRING("datacontainerevents"),
     272               0 :                       getter_AddRefs(event));
     273               0 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
     274               0 :   nsCOMPtr<nsIDOMDataContainerEvent> containerEvent(do_QueryInterface(event));
     275               0 :   if (!privateEvent || !containerEvent) {
     276               0 :     NS_WARNING("Couldn't QI event for PluginCrashed event!");
     277               0 :     return NS_OK;
     278                 :   }
     279                 : 
     280               0 :   event->InitEvent(NS_LITERAL_STRING("PluginCrashed"), true, true);
     281               0 :   privateEvent->SetTrusted(true);
     282               0 :   privateEvent->GetInternalNSEvent()->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH;
     283                 :   
     284               0 :   nsCOMPtr<nsIWritableVariant> variant;
     285                 : 
     286                 :   // add a "pluginDumpID" property to this event
     287               0 :   variant = do_CreateInstance("@mozilla.org/variant;1");
     288               0 :   if (!variant) {
     289               0 :     NS_WARNING("Couldn't create pluginDumpID variant for PluginCrashed event!");
     290               0 :     return NS_OK;
     291                 :   }
     292               0 :   variant->SetAsAString(mPluginDumpID);
     293               0 :   containerEvent->SetData(NS_LITERAL_STRING("pluginDumpID"), variant);
     294                 : 
     295                 :   // add a "browserDumpID" property to this event
     296               0 :   variant = do_CreateInstance("@mozilla.org/variant;1");
     297               0 :   if (!variant) {
     298               0 :     NS_WARNING("Couldn't create browserDumpID variant for PluginCrashed event!");
     299               0 :     return NS_OK;
     300                 :   }
     301               0 :   variant->SetAsAString(mBrowserDumpID);
     302               0 :   containerEvent->SetData(NS_LITERAL_STRING("browserDumpID"), variant);
     303                 : 
     304                 :   // add a "pluginName" property to this event
     305               0 :   variant = do_CreateInstance("@mozilla.org/variant;1");
     306               0 :   if (!variant) {
     307               0 :     NS_WARNING("Couldn't create pluginName variant for PluginCrashed event!");
     308               0 :     return NS_OK;
     309                 :   }
     310               0 :   variant->SetAsAString(mPluginName);
     311               0 :   containerEvent->SetData(NS_LITERAL_STRING("pluginName"), variant);
     312                 : 
     313                 :   // add a "pluginFilename" property to this event
     314               0 :   variant = do_CreateInstance("@mozilla.org/variant;1");
     315               0 :   if (!variant) {
     316               0 :     NS_WARNING("Couldn't create pluginFilename variant for PluginCrashed event!");
     317               0 :     return NS_OK;
     318                 :   }
     319               0 :   variant->SetAsAString(mPluginFilename);
     320               0 :   containerEvent->SetData(NS_LITERAL_STRING("pluginFilename"), variant);
     321                 : 
     322                 :   // add a "submittedCrashReport" property to this event
     323               0 :   variant = do_CreateInstance("@mozilla.org/variant;1");
     324               0 :   if (!variant) {
     325               0 :     NS_WARNING("Couldn't create crashSubmit variant for PluginCrashed event!");
     326               0 :     return NS_OK;
     327                 :   }
     328               0 :   variant->SetAsBool(mSubmittedCrashReport);
     329               0 :   containerEvent->SetData(NS_LITERAL_STRING("submittedCrashReport"), variant);
     330                 : 
     331               0 :   nsEventDispatcher::DispatchDOMEvent(mContent, nsnull, event, nsnull, nsnull);
     332               0 :   return NS_OK;
     333                 : }
     334                 : 
     335                 : class nsStopPluginRunnable : public nsRunnable, public nsITimerCallback
     336               0 : {
     337                 : public:
     338                 :   NS_DECL_ISUPPORTS_INHERITED
     339                 : 
     340               0 :   nsStopPluginRunnable(nsPluginInstanceOwner* aInstanceOwner,
     341                 :                        nsObjectLoadingContent* aContent)
     342                 :     : mInstanceOwner(aInstanceOwner)
     343               0 :     , mContent(aContent)
     344                 :   {
     345               0 :     NS_ASSERTION(aInstanceOwner, "need an owner");
     346               0 :     NS_ASSERTION(aContent, "need a nsObjectLoadingContent");
     347               0 :   }
     348                 : 
     349                 :   // nsRunnable
     350                 :   NS_IMETHOD Run();
     351                 : 
     352                 :   // nsITimerCallback
     353                 :   NS_IMETHOD Notify(nsITimer *timer);
     354                 : 
     355                 : private:
     356                 :   nsCOMPtr<nsITimer> mTimer;
     357                 :   nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
     358                 :   nsCOMPtr<nsIObjectLoadingContent> mContent;
     359                 : };
     360                 : 
     361               0 : NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
     362                 : 
     363                 : NS_IMETHODIMP
     364               0 : nsStopPluginRunnable::Notify(nsITimer *aTimer)
     365                 : {
     366               0 :   return Run();
     367                 : }
     368                 : 
     369                 : NS_IMETHODIMP
     370               0 : nsStopPluginRunnable::Run()
     371                 : {
     372                 :   // InitWithCallback calls Release before AddRef so we need to hold a
     373                 :   // strong ref on 'this' since we fall through to this scope if it fails.
     374               0 :   nsCOMPtr<nsITimerCallback> kungFuDeathGrip = this;
     375               0 :   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
     376               0 :   if (appShell) {
     377               0 :     PRUint32 currentLevel = 0;
     378               0 :     appShell->GetEventloopNestingLevel(&currentLevel);
     379               0 :     if (currentLevel > mInstanceOwner->GetLastEventloopNestingLevel()) {
     380               0 :       if (!mTimer)
     381               0 :         mTimer = do_CreateInstance("@mozilla.org/timer;1");
     382               0 :       if (mTimer) {
     383                 :         // Fire 100ms timer to try to tear down this plugin as quickly as
     384                 :         // possible once the nesting level comes back down.
     385               0 :         nsresult rv = mTimer->InitWithCallback(this, 100, nsITimer::TYPE_ONE_SHOT);
     386               0 :         if (NS_SUCCEEDED(rv)) {
     387               0 :           return rv;
     388                 :         }
     389                 :       }
     390                 :       NS_ERROR("Failed to setup a timer to stop the plugin later (at a safe "
     391               0 :                "time). Stopping the plugin now, this might crash.");
     392                 :     }
     393                 :   }
     394                 : 
     395               0 :   mTimer = nsnull;
     396                 : 
     397               0 :   static_cast<nsObjectLoadingContent*>(mContent.get())->
     398               0 :     DoStopPlugin(mInstanceOwner, false, true);
     399                 : 
     400               0 :   return NS_OK;
     401                 : }
     402                 : 
     403                 : class AutoNotifier {
     404                 :   public:
     405               0 :     AutoNotifier(nsObjectLoadingContent* aContent, bool aNotify) :
     406               0 :       mContent(aContent), mNotify(aNotify) {
     407               0 :         mOldType = aContent->Type();
     408               0 :         mOldState = aContent->ObjectState();
     409               0 :     }
     410               0 :     ~AutoNotifier() {
     411               0 :       mContent->NotifyStateChanged(mOldType, mOldState, false, mNotify);
     412               0 :     }
     413                 : 
     414                 :     /**
     415                 :      * Send notifications now, ignoring the value of mNotify. The new type and
     416                 :      * state is saved, and the destructor will notify again if mNotify is true
     417                 :      * and the values changed.
     418                 :      */
     419               0 :     void Notify() {
     420               0 :       NS_ASSERTION(mNotify, "Should not notify when notify=false");
     421                 : 
     422               0 :       mContent->NotifyStateChanged(mOldType, mOldState, true, true);
     423               0 :       mOldType = mContent->Type();
     424               0 :       mOldState = mContent->ObjectState();
     425               0 :     }
     426                 : 
     427                 :   private:
     428                 :     nsObjectLoadingContent*            mContent;
     429                 :     bool                               mNotify;
     430                 :     nsObjectLoadingContent::ObjectType mOldType;
     431                 :     nsEventStates                      mOldState;
     432                 : };
     433                 : 
     434                 : /**
     435                 :  * A class that will automatically fall back if a |rv| variable has a failure
     436                 :  * code when this class is destroyed. It does not notify.
     437                 :  */
     438                 : class AutoFallback {
     439                 :   public:
     440               0 :     AutoFallback(nsObjectLoadingContent* aContent, const nsresult* rv)
     441               0 :       : mContent(aContent), mResult(rv), mPluginState(ePluginOtherState) {}
     442               0 :     ~AutoFallback() {
     443               0 :       if (NS_FAILED(*mResult)) {
     444               0 :         LOG(("OBJLC [%p]: rv=%08x, falling back\n", mContent, *mResult));
     445               0 :         mContent->Fallback(false);
     446               0 :         if (mPluginState != ePluginOtherState) {
     447               0 :           mContent->mFallbackReason = mPluginState;
     448                 :         }
     449                 :       }
     450               0 :     }
     451                 : 
     452                 :     /**
     453                 :      * This should be set to something other than ePluginOtherState to indicate
     454                 :      * a specific failure that should be passed on.
     455                 :      */
     456               0 :      void SetPluginState(PluginSupportState aState) {
     457               0 :        NS_ASSERTION(aState != ePluginOtherState, "Should not be setting ePluginOtherState");
     458               0 :        mPluginState = aState;
     459               0 :      }
     460                 :   private:
     461                 :     nsObjectLoadingContent* mContent;
     462                 :     const nsresult* mResult;
     463                 :     PluginSupportState mPluginState;
     464                 : };
     465                 : 
     466                 : /**
     467                 :  * A class that automatically sets mInstantiating to false when it goes
     468                 :  * out of scope.
     469                 :  */
     470                 : class AutoSetInstantiatingToFalse {
     471                 :   public:
     472               0 :     AutoSetInstantiatingToFalse(nsObjectLoadingContent* objlc) : mContent(objlc) {}
     473               0 :     ~AutoSetInstantiatingToFalse() { mContent->mInstantiating = false; }
     474                 :   private:
     475                 :     nsObjectLoadingContent* mContent;
     476                 : };
     477                 : 
     478                 : // helper functions
     479                 : static bool
     480               0 : IsSupportedImage(const nsCString& aMimeType)
     481                 : {
     482               0 :   imgILoader* loader = nsContentUtils::GetImgLoader();
     483               0 :   if (!loader) {
     484               0 :     return false;
     485                 :   }
     486                 : 
     487                 :   bool supported;
     488               0 :   nsresult rv = loader->SupportImageWithMimeType(aMimeType.get(), &supported);
     489               0 :   return NS_SUCCEEDED(rv) && supported;
     490                 : }
     491                 : 
     492               0 : nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMEType)
     493                 : {
     494               0 :   if (!mShouldPlay) {
     495               0 :     return NS_ERROR_PLUGIN_CLICKTOPLAY;
     496                 :   }
     497                 : 
     498               0 :   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
     499               0 :   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
     500               0 :   if (!pluginHost) {
     501               0 :     return false;
     502                 :   }
     503               0 :   return pluginHost->IsPluginEnabledForType(aMIMEType.get());
     504                 : }
     505                 : 
     506                 : static void
     507               0 : GetExtensionFromURI(nsIURI* uri, nsCString& ext)
     508                 : {
     509               0 :   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
     510               0 :   if (url) {
     511               0 :     url->GetFileExtension(ext);
     512                 :   } else {
     513               0 :     nsCString spec;
     514               0 :     uri->GetSpec(spec);
     515                 : 
     516               0 :     PRInt32 offset = spec.RFindChar('.');
     517               0 :     if (offset != kNotFound) {
     518               0 :       ext = Substring(spec, offset + 1, spec.Length());
     519                 :     }
     520                 :   }
     521               0 : }
     522                 : 
     523                 : /**
     524                 :  * Checks whether a plugin exists and is enabled for the extension
     525                 :  * in the given URI. The MIME type is returned in the mimeType out parameter.
     526                 :  */
     527               0 : bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
     528                 : {
     529               0 :   if (!mShouldPlay) {
     530               0 :     return false;
     531                 :   }
     532                 : 
     533               0 :   nsCAutoString ext;
     534               0 :   GetExtensionFromURI(uri, ext);
     535                 : 
     536               0 :   if (ext.IsEmpty()) {
     537               0 :     return false;
     538                 :   }
     539                 : 
     540               0 :   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
     541               0 :   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
     542               0 :   if (!pluginHost) {
     543               0 :     return false;
     544                 :   }
     545                 : 
     546                 :   const char* typeFromExt;
     547               0 :   if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
     548               0 :     mimeType = typeFromExt;
     549               0 :     return true;
     550                 :   }
     551               0 :   return false;
     552                 : }
     553                 : 
     554               0 : nsObjectLoadingContent::nsObjectLoadingContent()
     555                 :   : mPendingInstantiateEvent(nsnull)
     556                 :   , mChannel(nsnull)
     557                 :   , mType(eType_Loading)
     558                 :   , mInstantiating(false)
     559                 :   , mUserDisabled(false)
     560                 :   , mSuppressed(false)
     561                 :   , mNetworkCreated(true)
     562                 :   // If plugins.click_to_play is false, plugins should always play
     563               0 :   , mShouldPlay(!mozilla::Preferences::GetBool("plugins.click_to_play", false))
     564                 :   , mIsStopping(false)
     565                 :   , mSrcStreamLoading(false)
     566               0 :   , mFallbackReason(ePluginOtherState)
     567                 : {
     568               0 : }
     569                 : 
     570               0 : nsObjectLoadingContent::~nsObjectLoadingContent()
     571                 : {
     572               0 :   DestroyImageLoadingContent();
     573               0 :   if (mFrameLoader) {
     574               0 :     mFrameLoader->Destroy();
     575                 :   }
     576               0 : }
     577                 : 
     578                 : nsresult
     579               0 : nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI)
     580                 : {
     581               0 :   if (!mShouldPlay) {
     582               0 :     return NS_ERROR_PLUGIN_CLICKTOPLAY;
     583                 :   }
     584                 : 
     585                 :   // Don't do anything if we already have an active instance.
     586               0 :   if (mInstanceOwner) {
     587               0 :     return NS_OK;
     588                 :   }
     589                 : 
     590                 :   // Don't allow re-entry into initialization code.
     591               0 :   if (mInstantiating) {
     592               0 :     return NS_OK;
     593                 :   }
     594               0 :   mInstantiating = true;
     595               0 :   AutoSetInstantiatingToFalse autoInstantiating(this);
     596                 : 
     597                 :   // Instantiating an instance can result in script execution, which
     598                 :   // can destroy this DOM object. Don't allow that for the scope
     599                 :   // of this method.
     600               0 :   nsCOMPtr<nsIObjectLoadingContent> kungFuDeathGrip = this;
     601               0 :   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
     602                 : 
     603               0 :   nsCOMPtr<nsIURI> baseURI;
     604               0 :   if (!aURI) {
     605                 :     // We need some URI. If we have nothing else, use the base URI.
     606                 :     // XXX(biesi): The code used to do this. Not sure why this is correct...
     607               0 :     GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
     608               0 :     aURI = baseURI;
     609                 :   }
     610                 : 
     611                 :   // Flush layout so that the plugin is initialized with the latest information.
     612               0 :   nsIDocument* doc = thisContent->GetCurrentDoc();
     613               0 :   if (!doc) {
     614               0 :     return NS_ERROR_FAILURE;
     615                 :   }
     616               0 :   if (!doc->IsActive()) {
     617               0 :     NS_ERROR("Shouldn't be calling InstantiatePluginInstance in an inactive document");
     618               0 :     return NS_ERROR_FAILURE;
     619                 :   }
     620               0 :   doc->FlushPendingNotifications(Flush_Layout);
     621                 : 
     622               0 :   nsresult rv = NS_ERROR_FAILURE;
     623               0 :   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv));
     624               0 :   nsPluginHost* pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
     625               0 :   if (NS_FAILED(rv)) {
     626               0 :     return rv;
     627                 :   }
     628                 : 
     629                 :   // If you add early return(s), be sure to balance this call to
     630                 :   // appShell->SuspendNative() with additional call(s) to
     631                 :   // appShell->ReturnNative().
     632               0 :   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
     633               0 :   if (appShell) {
     634               0 :     appShell->SuspendNative();
     635                 :   }
     636                 : 
     637               0 :   nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(doc));
     638               0 :   bool fullPageMode = false;
     639               0 :   if (pDoc) {
     640               0 :     pDoc->GetWillHandleInstantiation(&fullPageMode);
     641                 :   }
     642                 : 
     643               0 :   if (fullPageMode) {
     644               0 :     nsCOMPtr<nsIStreamListener> stream;
     645               0 :     rv = pluginHost->InstantiateFullPagePlugin(aMimeType, aURI, this, getter_AddRefs(mInstanceOwner), getter_AddRefs(stream));
     646               0 :     if (NS_SUCCEEDED(rv)) {
     647               0 :       pDoc->SetStreamListener(stream);
     648                 :     }
     649                 :   } else {
     650               0 :     rv = pluginHost->InstantiateEmbeddedPlugin(aMimeType, aURI, this, getter_AddRefs(mInstanceOwner));
     651                 :   }
     652                 : 
     653               0 :   if (appShell) {
     654               0 :     appShell->ResumeNative();
     655                 :   }
     656                 : 
     657               0 :   if (NS_FAILED(rv)) {
     658               0 :     return rv;
     659                 :   }
     660                 : 
     661                 :   // Set up scripting interfaces.
     662               0 :   NotifyContentObjectWrapper();
     663                 : 
     664               0 :   nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
     665               0 :   GetPluginInstance(getter_AddRefs(pluginInstance));
     666               0 :   if (pluginInstance) {
     667               0 :     nsCOMPtr<nsIPluginTag> pluginTag;
     668               0 :     pluginHost->GetPluginTagForInstance(pluginInstance, getter_AddRefs(pluginTag));
     669                 :     
     670                 :     nsCOMPtr<nsIBlocklistService> blocklist =
     671               0 :     do_GetService("@mozilla.org/extensions/blocklist;1");
     672               0 :     if (blocklist) {
     673               0 :       PRUint32 blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
     674               0 :       blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
     675               0 :                                          EmptyString(), &blockState);
     676               0 :       if (blockState == nsIBlocklistService::STATE_OUTDATED)
     677               0 :         FirePluginError(thisContent, ePluginOutdated);
     678                 :     }
     679                 :   }
     680                 : 
     681               0 :   return NS_OK;
     682                 : }
     683                 : 
     684                 : void
     685               0 : nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged()
     686                 : {
     687               0 :   if (!mInstanceOwner) {
     688               0 :     return;
     689                 :   }
     690                 : 
     691               0 :   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
     692               0 :   nsIDocument* ownerDoc = thisContent->OwnerDoc();
     693               0 :   if (!ownerDoc->IsActive()) {
     694               0 :     StopPluginInstance();
     695                 :   }
     696                 : }
     697                 : 
     698                 : // nsIRequestObserver
     699                 : NS_IMETHODIMP
     700               0 : nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
     701                 :                                        nsISupports *aContext)
     702                 : {
     703               0 :   SAMPLE_LABEL("nsObjectLoadingContent", "OnStartRequest");
     704                 : 
     705               0 :   if (aRequest != mChannel || !aRequest) {
     706                 :     // This is a bit of an edge case - happens when a new load starts before the
     707                 :     // previous one got here
     708               0 :     return NS_BINDING_ABORTED;
     709                 :   }
     710                 : 
     711               0 :   AutoNotifier notifier(this, true);
     712                 : 
     713               0 :   if (!IsSuccessfulRequest(aRequest)) {
     714               0 :     LOG(("OBJLC [%p]: OnStartRequest: Request failed\n", this));
     715               0 :     Fallback(false);
     716               0 :     return NS_BINDING_ABORTED;
     717                 :   }
     718                 : 
     719               0 :   nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
     720               0 :   NS_ASSERTION(chan, "Why is our request not a channel?");
     721                 : 
     722               0 :   nsresult rv = NS_ERROR_UNEXPECTED;
     723                 :   // This fallback variable MUST be declared after the notifier variable. Do NOT
     724                 :   // change the order of the declarations!
     725               0 :   AutoFallback fallback(this, &rv);
     726                 : 
     727               0 :   nsCString channelType;
     728               0 :   rv = chan->GetContentType(channelType);
     729               0 :   NS_ENSURE_SUCCESS(rv, rv);
     730                 : 
     731               0 :   if (channelType.EqualsASCII(APPLICATION_GUESS_FROM_EXT)) {
     732               0 :     channelType = APPLICATION_OCTET_STREAM;
     733               0 :     chan->SetContentType(channelType);
     734                 :   }
     735                 : 
     736                 :   // We want to use the channel type unless one of the following is true:
     737                 :   //
     738                 :   // 1) The channel type is application/octet-stream and we have a
     739                 :   //    type hint and the type hint is not a document type.
     740                 :   // 2) Our type hint is a type that we support with a plugin.
     741               0 :   if ((channelType.EqualsASCII(APPLICATION_OCTET_STREAM) && 
     742               0 :        !mContentType.IsEmpty() &&
     743               0 :        GetTypeOfContent(mContentType) != eType_Document) ||
     744                 :       // Need to check IsPluginEnabledForType() in addition to GetTypeOfContent()
     745                 :       // because otherwise the default plug-in's catch-all behavior would
     746                 :       // confuse things.
     747               0 :       (NS_SUCCEEDED(IsPluginEnabledForType(mContentType)) && 
     748               0 :        GetTypeOfContent(mContentType) == eType_Plugin)) {
     749                 :     // Set the type we'll use for dispatch on the channel.  Otherwise we could
     750                 :     // end up trying to dispatch to a nsFrameLoader, which will complain that
     751                 :     // it couldn't find a way to handle application/octet-stream
     752               0 :     nsCAutoString typeHint, dummy;
     753               0 :     NS_ParseContentType(mContentType, typeHint, dummy);
     754               0 :     if (!typeHint.IsEmpty()) {
     755               0 :       chan->SetContentType(typeHint);
     756                 :     }
     757                 :   } else {
     758               0 :     mContentType = channelType;
     759                 :   }
     760                 : 
     761               0 :   nsCOMPtr<nsIURI> uri;
     762               0 :   chan->GetURI(getter_AddRefs(uri));
     763                 : 
     764               0 :   if (mContentType.EqualsASCII(APPLICATION_OCTET_STREAM)) {
     765               0 :     nsCAutoString extType;
     766               0 :     if (IsPluginEnabledByExtension(uri, extType)) {
     767               0 :       mContentType = extType;
     768               0 :       chan->SetContentType(extType);
     769                 :     }
     770                 :   }
     771                 : 
     772                 :   // Now find out what type the content is
     773                 :   // UnloadContent will set our type to null; need to be sure to only set it to
     774                 :   // the real value on success
     775               0 :   ObjectType newType = GetTypeOfContent(mContentType);
     776               0 :   LOG(("OBJLC [%p]: OnStartRequest: Content Type=<%s> Old type=%u New Type=%u\n",
     777                 :        this, mContentType.get(), mType, newType));
     778                 : 
     779                 :   // Now do a content policy check
     780                 :   // XXXbz this duplicates some code in nsContentBlocker::ShouldLoad  
     781                 :   PRInt32 contentPolicyType;
     782               0 :   switch (newType) {
     783                 :     case eType_Image:
     784               0 :       contentPolicyType = nsIContentPolicy::TYPE_IMAGE;
     785               0 :       break;
     786                 :     case eType_Document:
     787               0 :       contentPolicyType = nsIContentPolicy::TYPE_SUBDOCUMENT;
     788               0 :       break;
     789                 :     default:
     790               0 :       contentPolicyType = nsIContentPolicy::TYPE_OBJECT;
     791               0 :       break;
     792                 :   }
     793                 :   nsCOMPtr<nsIContent> thisContent = 
     794               0 :     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
     795               0 :   NS_ASSERTION(thisContent, "must be a content");
     796                 : 
     797               0 :   nsIDocument* doc = thisContent->OwnerDoc();
     798                 : 
     799               0 :   PRInt16 shouldProcess = nsIContentPolicy::ACCEPT;
     800                 :   rv =
     801                 :     NS_CheckContentProcessPolicy(contentPolicyType,
     802                 :                                  uri,
     803                 :                                  doc->NodePrincipal(),
     804                 :                                  static_cast<nsIImageLoadingContent*>(this),
     805                 :                                  mContentType,
     806                 :                                  nsnull, //extra
     807                 :                                  &shouldProcess,
     808                 :                                  nsContentUtils::GetContentPolicy(),
     809               0 :                                  nsContentUtils::GetSecurityManager());
     810               0 :   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldProcess)) {
     811               0 :     HandleBeingBlockedByContentPolicy(rv, shouldProcess);
     812               0 :     rv = NS_OK; // otherwise, the AutoFallback will make us fall back
     813               0 :     return NS_BINDING_ABORTED;
     814                 :   }  
     815                 :   
     816               0 :   if (mType != newType) {
     817               0 :     UnloadContent();
     818                 :   }
     819                 : 
     820               0 :   switch (newType) {
     821                 :     case eType_Image:
     822               0 :       rv = LoadImageWithChannel(chan, getter_AddRefs(mFinalListener));
     823               0 :       NS_ENSURE_SUCCESS(rv, rv);
     824                 : 
     825                 :       // If we have a success result but no final listener, then the image is
     826                 :       // cached. In that case, we can just return: No need to try to call the
     827                 :       // final listener.
     828               0 :       if (!mFinalListener) {
     829               0 :         mType = newType;
     830               0 :         return NS_BINDING_ABORTED;
     831                 :       }
     832               0 :       break;
     833                 :     case eType_Document: {
     834               0 :       if (!mFrameLoader) {
     835               0 :         mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
     836               0 :                                              mNetworkCreated);
     837               0 :         if (!mFrameLoader) {
     838               0 :           Fallback(false);
     839               0 :           return NS_ERROR_UNEXPECTED;
     840                 :         }
     841                 :       }
     842                 : 
     843               0 :       rv = mFrameLoader->CheckForRecursiveLoad(uri);
     844               0 :       if (NS_FAILED(rv)) {
     845               0 :         Fallback(false);
     846               0 :         return rv;
     847                 :       }
     848                 : 
     849               0 :       if (mType != newType) {
     850                 :         // XXX We must call this before getting the docshell to work around
     851                 :         // bug 300540; when that's fixed, this if statement can be removed.
     852               0 :         mType = newType;
     853               0 :         notifier.Notify();
     854                 : 
     855               0 :         if (!mFrameLoader) {
     856                 :           // mFrameLoader got nulled out when we notified, which most
     857                 :           // likely means the node was removed from the
     858                 :           // document. Abort the load that just started.
     859               0 :           return NS_BINDING_ABORTED;
     860                 :         }
     861                 :       }
     862                 : 
     863                 :       // We're loading a document, so we have to set LOAD_DOCUMENT_URI
     864                 :       // (especially important for firing onload)
     865               0 :       nsLoadFlags flags = 0;
     866               0 :       chan->GetLoadFlags(&flags);
     867               0 :       flags |= nsIChannel::LOAD_DOCUMENT_URI;
     868               0 :       chan->SetLoadFlags(flags);
     869                 : 
     870               0 :       nsCOMPtr<nsIDocShell> docShell;
     871               0 :       rv = mFrameLoader->GetDocShell(getter_AddRefs(docShell));
     872               0 :       NS_ENSURE_SUCCESS(rv, rv);
     873                 : 
     874               0 :       nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(docShell));
     875               0 :       NS_ASSERTION(req, "Docshell must be an ifreq");
     876                 : 
     877                 :       nsCOMPtr<nsIURILoader>
     878               0 :         uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID, &rv));
     879               0 :       NS_ENSURE_SUCCESS(rv, rv);
     880               0 :       rv = uriLoader->OpenChannel(chan, nsIURILoader::DONT_RETARGET, req,
     881               0 :                                   getter_AddRefs(mFinalListener));
     882               0 :       break;
     883                 :     }
     884                 :     case eType_Plugin: {
     885               0 :       if (mType != newType) {
     886               0 :         mType = newType;
     887               0 :         notifier.Notify();
     888                 :       }
     889               0 :       nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
     890               0 :       nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
     891               0 :       if (!pluginHost) {
     892               0 :         return NS_ERROR_NOT_AVAILABLE;
     893                 :       }
     894               0 :       pluginHost->CreateListenerForChannel(chan, this, getter_AddRefs(mFinalListener));
     895               0 :       break;
     896                 :     }
     897                 :     case eType_Loading:
     898               0 :       NS_NOTREACHED("Should not have a loading type here!");
     899                 :     case eType_Null:
     900                 :       // Need to fallback here (instead of using the case below), so that we can
     901                 :       // set mFallbackReason without it being overwritten. This is also why we
     902                 :       // return early.
     903               0 :       Fallback(false);
     904                 : 
     905                 :       PluginSupportState pluginState = GetPluginSupportState(thisContent,
     906               0 :                                                              mContentType);
     907                 :       // Do nothing, but fire the plugin not found event if needed
     908               0 :       if (pluginState != ePluginOtherState) {
     909               0 :         mFallbackReason = pluginState;
     910               0 :         FirePluginError(thisContent, pluginState);
     911                 :       }
     912               0 :       return NS_BINDING_ABORTED;
     913                 :   }
     914                 : 
     915               0 :   if (mFinalListener) {
     916               0 :     mType = newType;
     917                 : 
     918               0 :     mSrcStreamLoading = true;
     919               0 :     rv = mFinalListener->OnStartRequest(aRequest, aContext);
     920               0 :     mSrcStreamLoading = false;
     921                 : 
     922               0 :     if (NS_SUCCEEDED(rv)) {
     923                 :       // Plugins need to set up for NPRuntime.
     924               0 :       if (mType == eType_Plugin) {
     925               0 :         NotifyContentObjectWrapper();
     926                 :       }
     927                 :     } else {
     928                 :       // Plugins don't fall back if there is an error here.
     929               0 :       if (mType == eType_Plugin) {
     930               0 :         rv = NS_OK; // this is necessary to avoid auto-fallback
     931               0 :         return NS_BINDING_ABORTED;
     932                 :       }
     933               0 :       Fallback(false);
     934                 :     }
     935                 : 
     936               0 :     return rv;
     937                 :   }
     938                 : 
     939               0 :   Fallback(false);
     940               0 :   return NS_BINDING_ABORTED;
     941                 : }
     942                 : 
     943                 : NS_IMETHODIMP
     944               0 : nsObjectLoadingContent::OnStopRequest(nsIRequest *aRequest,
     945                 :                                       nsISupports *aContext,
     946                 :                                       nsresult aStatusCode)
     947                 : {
     948               0 :   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
     949                 : 
     950               0 :   if (aRequest != mChannel) {
     951               0 :     return NS_BINDING_ABORTED;
     952                 :   }
     953                 : 
     954               0 :   mChannel = nsnull;
     955                 : 
     956               0 :   if (mFinalListener) {
     957               0 :     mFinalListener->OnStopRequest(aRequest, aContext, aStatusCode);
     958               0 :     mFinalListener = nsnull;
     959                 :   }
     960                 : 
     961                 :   // Return value doesn't matter
     962               0 :   return NS_OK;
     963                 : }
     964                 : 
     965                 : 
     966                 : // nsIStreamListener
     967                 : NS_IMETHODIMP
     968               0 : nsObjectLoadingContent::OnDataAvailable(nsIRequest *aRequest,
     969                 :                                         nsISupports *aContext,
     970                 :                                         nsIInputStream *aInputStream,
     971                 :                                         PRUint32 aOffset, PRUint32 aCount)
     972                 : {
     973               0 :   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
     974                 : 
     975               0 :   if (aRequest != mChannel) {
     976               0 :     return NS_BINDING_ABORTED;
     977                 :   }
     978                 : 
     979               0 :   if (mFinalListener) {
     980               0 :     return mFinalListener->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
     981                 :   }
     982                 : 
     983                 :   // Abort this load if we have no listener here
     984               0 :   return NS_ERROR_UNEXPECTED;
     985                 : }
     986                 : 
     987                 : // nsIFrameLoaderOwner
     988                 : NS_IMETHODIMP
     989               0 : nsObjectLoadingContent::GetFrameLoader(nsIFrameLoader** aFrameLoader)
     990                 : {
     991               0 :   *aFrameLoader = mFrameLoader;
     992               0 :   NS_IF_ADDREF(*aFrameLoader);
     993               0 :   return NS_OK;
     994                 : }
     995                 : 
     996                 : NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
     997               0 : nsObjectLoadingContent::GetFrameLoader()
     998                 : {
     999               0 :   nsFrameLoader* loader = mFrameLoader;
    1000               0 :   NS_IF_ADDREF(loader);
    1001               0 :   return loader;
    1002                 : }
    1003                 : 
    1004                 : NS_IMETHODIMP
    1005               0 : nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader)
    1006                 : {
    1007               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1008                 : }
    1009                 : 
    1010                 : // nsIObjectLoadingContent
    1011                 : NS_IMETHODIMP
    1012               0 : nsObjectLoadingContent::GetActualType(nsACString& aType)
    1013                 : {
    1014               0 :   aType = mContentType;
    1015               0 :   return NS_OK;
    1016                 : }
    1017                 : 
    1018                 : NS_IMETHODIMP
    1019               0 : nsObjectLoadingContent::GetDisplayedType(PRUint32* aType)
    1020                 : {
    1021               0 :   *aType = mType;
    1022               0 :   return NS_OK;
    1023                 : }
    1024                 : 
    1025                 : NS_IMETHODIMP
    1026               0 : nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
    1027                 : {
    1028                 :   // Not having an instance yet is OK, but try to start one now that
    1029                 :   // we have a frame.
    1030               0 :   if (!mInstanceOwner) {
    1031               0 :     AsyncStartPluginInstance();
    1032               0 :     return NS_OK;
    1033                 :   }
    1034                 : 
    1035                 :   // Disconnect any existing frame
    1036               0 :   DisconnectFrame();
    1037                 : 
    1038                 :   // Set up relationship between instance owner and frame.
    1039               0 :   nsObjectFrame *objFrame = static_cast<nsObjectFrame*>(aFrame);
    1040               0 :   mInstanceOwner->SetFrame(objFrame);
    1041                 : 
    1042                 :   // Set up new frame to draw.
    1043               0 :   objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size());
    1044               0 :   objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf());
    1045                 : 
    1046               0 :   return NS_OK;
    1047                 : }
    1048                 : 
    1049                 : NS_IMETHODIMP
    1050               0 : nsObjectLoadingContent::DisconnectFrame()
    1051                 : {
    1052               0 :   if (mInstanceOwner) {
    1053               0 :     mInstanceOwner->SetFrame(nsnull);
    1054                 :   }
    1055               0 :   return NS_OK;
    1056                 : }
    1057                 : 
    1058                 : NS_IMETHODIMP
    1059               0 : nsObjectLoadingContent::GetPluginInstance(nsNPAPIPluginInstance** aInstance)
    1060                 : {
    1061               0 :   *aInstance = nsnull;
    1062                 : 
    1063               0 :   if (!mInstanceOwner) {
    1064               0 :     return NS_OK;
    1065                 :   }
    1066                 : 
    1067               0 :   return mInstanceOwner->GetInstance(aInstance);
    1068                 : }
    1069                 : 
    1070                 : NS_IMETHODIMP
    1071               0 : nsObjectLoadingContent::GetContentTypeForMIMEType(const nsACString& aMIMEType,
    1072                 :                                                   PRUint32* aType)
    1073                 : {
    1074               0 :   *aType = GetTypeOfContent(PromiseFlatCString(aMIMEType));
    1075               0 :   return NS_OK;
    1076                 : }
    1077                 : 
    1078                 : // nsIInterfaceRequestor
    1079                 : NS_IMETHODIMP
    1080               0 : nsObjectLoadingContent::GetInterface(const nsIID & aIID, void **aResult)
    1081                 : {
    1082               0 :   if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
    1083               0 :     nsIChannelEventSink* sink = this;
    1084               0 :     *aResult = sink;
    1085               0 :     NS_ADDREF(sink);
    1086               0 :     return NS_OK;
    1087                 :   }
    1088               0 :   return NS_NOINTERFACE;
    1089                 : }
    1090                 : 
    1091                 : // nsIChannelEventSink
    1092                 : NS_IMETHODIMP
    1093               0 : nsObjectLoadingContent::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
    1094                 :                                                nsIChannel *aNewChannel,
    1095                 :                                                PRUint32 aFlags,
    1096                 :                                                nsIAsyncVerifyRedirectCallback *cb)
    1097                 : {
    1098                 :   // If we're already busy with a new load, or have no load at all,
    1099                 :   // cancel the redirect.
    1100               0 :   if (!mChannel || aOldChannel != mChannel) {
    1101               0 :     return NS_BINDING_ABORTED;
    1102                 :   }
    1103                 : 
    1104               0 :   mChannel = aNewChannel;
    1105               0 :   cb->OnRedirectVerifyCallback(NS_OK);
    1106               0 :   return NS_OK;
    1107                 : }
    1108                 : 
    1109                 : // <public>
    1110                 : nsEventStates
    1111               0 : nsObjectLoadingContent::ObjectState() const
    1112                 : {
    1113               0 :   switch (mType) {
    1114                 :     case eType_Loading:
    1115               0 :       return NS_EVENT_STATE_LOADING;
    1116                 :     case eType_Image:
    1117               0 :       return ImageState();
    1118                 :     case eType_Plugin:
    1119                 :     case eType_Document:
    1120                 :       // These are OK. If documents start to load successfully, they display
    1121                 :       // something, and are thus not broken in this sense. The same goes for
    1122                 :       // plugins.
    1123               0 :       return nsEventStates();
    1124                 :     case eType_Null:
    1125               0 :       if (mSuppressed)
    1126               0 :         return NS_EVENT_STATE_SUPPRESSED;
    1127               0 :       if (mUserDisabled)
    1128               0 :         return NS_EVENT_STATE_USERDISABLED;
    1129                 : 
    1130                 :       // Otherwise, broken
    1131               0 :       nsEventStates state = NS_EVENT_STATE_BROKEN;
    1132               0 :       switch (mFallbackReason) {
    1133                 :         case ePluginClickToPlay:
    1134               0 :           return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
    1135                 :         case ePluginDisabled:
    1136               0 :           state |= NS_EVENT_STATE_HANDLER_DISABLED;
    1137               0 :           break;
    1138                 :         case ePluginBlocklisted:
    1139               0 :           state |= NS_EVENT_STATE_HANDLER_BLOCKED;
    1140               0 :           break;
    1141                 :         case ePluginCrashed:
    1142               0 :           state |= NS_EVENT_STATE_HANDLER_CRASHED;
    1143               0 :           break;
    1144                 :         case ePluginUnsupported:
    1145               0 :           state |= NS_EVENT_STATE_TYPE_UNSUPPORTED;
    1146               0 :           break;
    1147                 :         case ePluginOutdated:
    1148                 :         case ePluginOtherState:
    1149                 :           // Do nothing, but avoid a compile warning
    1150               0 :           break;
    1151                 :       }
    1152               0 :       return state;
    1153                 :   };
    1154               0 :   NS_NOTREACHED("unknown type?");
    1155                 :   // this return statement only exists to avoid a compile warning
    1156               0 :   return nsEventStates();
    1157                 : }
    1158                 : 
    1159                 : // <protected>
    1160                 : nsresult
    1161               0 : nsObjectLoadingContent::LoadObject(const nsAString& aURI,
    1162                 :                                    bool aNotify,
    1163                 :                                    const nsCString& aTypeHint,
    1164                 :                                    bool aForceLoad)
    1165                 : {
    1166               0 :   LOG(("OBJLC [%p]: Loading object: URI string=<%s> notify=%i type=<%s> forceload=%i\n",
    1167                 :        this, NS_ConvertUTF16toUTF8(aURI).get(), aNotify, aTypeHint.get(), aForceLoad));
    1168                 : 
    1169                 :   // Avoid StringToURI in order to use the codebase attribute as base URI
    1170                 :   nsCOMPtr<nsIContent> thisContent = 
    1171               0 :     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1172               0 :   NS_ASSERTION(thisContent, "must be a content");
    1173                 : 
    1174               0 :   nsIDocument* doc = thisContent->OwnerDoc();
    1175               0 :   nsCOMPtr<nsIURI> baseURI;
    1176               0 :   GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
    1177                 : 
    1178               0 :   nsCOMPtr<nsIURI> uri;
    1179               0 :   nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
    1180                 :                                             aURI, doc,
    1181               0 :                                             baseURI);
    1182                 :   // If URI creation failed, fallback immediately - this only happens for
    1183                 :   // malformed URIs
    1184               0 :   if (!uri) {
    1185               0 :     Fallback(aNotify);
    1186               0 :     return NS_OK;
    1187                 :   }
    1188                 : 
    1189               0 :   NS_TryToSetImmutable(uri);
    1190                 : 
    1191               0 :   return LoadObject(uri, aNotify, aTypeHint, aForceLoad);
    1192                 : }
    1193                 : 
    1194                 : void
    1195               0 : nsObjectLoadingContent::UpdateFallbackState(nsIContent* aContent,
    1196                 :                                             AutoFallback& fallback,
    1197                 :                                             const nsCString& aTypeHint)
    1198                 : {
    1199                 :   // Notify the UI and update the fallback state
    1200               0 :   PluginSupportState state = GetPluginSupportState(aContent, aTypeHint);
    1201               0 :   if (state != ePluginOtherState) {
    1202               0 :     fallback.SetPluginState(state);
    1203               0 :     FirePluginError(aContent, state);
    1204                 :   }
    1205               0 : }
    1206                 : 
    1207                 : nsresult
    1208               0 : nsObjectLoadingContent::LoadObject(nsIURI* aURI,
    1209                 :                                    bool aNotify,
    1210                 :                                    const nsCString& aTypeHint,
    1211                 :                                    bool aForceLoad)
    1212                 : {
    1213                 :   // Only do a URI equality check for things that aren't stopped plugins.
    1214                 :   // This is because we still need to load again if the plugin has been stopped.
    1215               0 :   if (mType == eType_Document || mType == eType_Image || mInstanceOwner) {
    1216               0 :     if (mURI && aURI) {
    1217                 :       bool equal;
    1218               0 :       nsresult rv = mURI->Equals(aURI, &equal);
    1219               0 :       if (NS_SUCCEEDED(rv) && equal && !aForceLoad) {
    1220                 :         // URI didn't change, do nothing
    1221               0 :         return NS_OK;
    1222                 :       }
    1223               0 :       StopPluginInstance();
    1224                 :     }
    1225                 :   }
    1226                 : 
    1227                 :   // Need to revoke any potentially pending instantiate events
    1228               0 :   if (mType == eType_Plugin && mPendingInstantiateEvent) {
    1229               0 :     mPendingInstantiateEvent = nsnull;
    1230                 :   }
    1231                 : 
    1232               0 :   AutoNotifier notifier(this, aNotify);
    1233                 : 
    1234               0 :   mUserDisabled = mSuppressed = false;
    1235                 : 
    1236               0 :   mURI = aURI;
    1237               0 :   mContentType = aTypeHint;
    1238                 : 
    1239                 :   nsCOMPtr<nsIContent> thisContent = 
    1240               0 :     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1241               0 :   NS_ASSERTION(thisContent, "must be a content");
    1242                 : 
    1243               0 :   nsIDocument* doc = thisContent->OwnerDoc();
    1244               0 :   if (doc->IsBeingUsedAsImage()) {
    1245               0 :     return NS_OK;
    1246                 :   }
    1247                 : 
    1248                 :   // From here on, we will always change the content. This means that a
    1249                 :   // possibly-loading channel should be aborted.
    1250               0 :   if (mChannel) {
    1251               0 :     LOG(("OBJLC [%p]: Cancelling existing load\n", this));
    1252                 : 
    1253                 :     // These three statements are carefully ordered:
    1254                 :     // - onStopRequest should get a channel whose status is the same as the
    1255                 :     //   status argument
    1256                 :     // - onStopRequest must get a non-null channel
    1257               0 :     mChannel->Cancel(NS_BINDING_ABORTED);
    1258               0 :     if (mFinalListener) {
    1259                 :       // NOTE: Since mFinalListener is only set in onStartRequest, which takes
    1260                 :       // care of calling mFinalListener->OnStartRequest, mFinalListener is only
    1261                 :       // non-null here if onStartRequest was already called.
    1262               0 :       mFinalListener->OnStopRequest(mChannel, nsnull, NS_BINDING_ABORTED);
    1263               0 :       mFinalListener = nsnull;
    1264                 :     }
    1265               0 :     mChannel = nsnull;
    1266                 :   }
    1267                 : 
    1268                 :   // Security checks
    1269               0 :   if (doc->IsLoadedAsData()) {
    1270               0 :     if (!doc->IsStaticDocument()) {
    1271               0 :       Fallback(false);
    1272                 :     }
    1273               0 :     return NS_OK;
    1274                 :   }
    1275                 : 
    1276                 :   // Can't do security checks without a URI - hopefully the plugin will take
    1277                 :   // care of that
    1278                 :   // Null URIs happen when the URL to load is specified via other means than the
    1279                 :   // data/src attribute, for example via custom <param> elements.
    1280               0 :   if (aURI) {
    1281               0 :     nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
    1282               0 :     NS_ASSERTION(secMan, "No security manager!?");
    1283                 :     nsresult rv =
    1284               0 :       secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), aURI, 0);
    1285               0 :     if (NS_FAILED(rv)) {
    1286               0 :       Fallback(false);
    1287               0 :       return NS_OK;
    1288                 :     }
    1289                 : 
    1290               0 :     PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; // default permit
    1291                 :     rv =
    1292                 :       NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OBJECT,
    1293                 :                                 aURI,
    1294                 :                                 doc->NodePrincipal(),
    1295                 :                                 static_cast<nsIImageLoadingContent*>(this),
    1296                 :                                 aTypeHint,
    1297                 :                                 nsnull, //extra
    1298                 :                                 &shouldLoad,
    1299                 :                                 nsContentUtils::GetContentPolicy(),
    1300               0 :                                 secMan);
    1301               0 :     if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
    1302               0 :       HandleBeingBlockedByContentPolicy(rv, shouldLoad);
    1303               0 :       return NS_OK;
    1304                 :     }
    1305                 :   }
    1306                 : 
    1307               0 :   nsresult rv = NS_ERROR_UNEXPECTED;
    1308                 :   // This fallback variable MUST be declared after the notifier variable. Do NOT
    1309                 :   // change the order of the declarations!
    1310               0 :   AutoFallback fallback(this, &rv);
    1311                 : 
    1312               0 :   PRUint32 caps = GetCapabilities();
    1313               0 :   LOG(("OBJLC [%p]: Capabilities: %04x\n", this, caps));
    1314                 : 
    1315               0 :   nsCAutoString overrideType;
    1316               0 :   if ((caps & eOverrideServerType) &&
    1317               0 :       ((!aTypeHint.IsEmpty() && NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) ||
    1318               0 :        (aURI && IsPluginEnabledByExtension(aURI, overrideType)))) {
    1319                 :     ObjectType newType;
    1320               0 :     if (overrideType.IsEmpty()) {
    1321               0 :       newType = GetTypeOfContent(aTypeHint);
    1322                 :     } else {
    1323               0 :       mContentType = overrideType;
    1324               0 :       newType = eType_Plugin;
    1325                 :     }
    1326                 : 
    1327               0 :     if (newType != mType) {
    1328               0 :       LOG(("OBJLC [%p]: (eOverrideServerType) Changing type from %u to %u\n", this, mType, newType));
    1329                 : 
    1330               0 :       UnloadContent();
    1331                 : 
    1332                 :       // Must have a frameloader before creating a frame, or the frame will
    1333                 :       // create its own.
    1334               0 :       if (!mFrameLoader && newType == eType_Document) {
    1335               0 :         mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
    1336               0 :                                              mNetworkCreated);
    1337               0 :         if (!mFrameLoader) {
    1338               0 :           mURI = nsnull;
    1339               0 :           return NS_OK;
    1340                 :         }
    1341                 :       }
    1342                 : 
    1343                 :       // Must notify here for plugins
    1344                 :       // If aNotify is false, we'll just wait until we get a frame and use the
    1345                 :       // async instantiate path.
    1346                 :       // XXX is this still needed? (for documents?)
    1347               0 :       mType = newType;
    1348               0 :       if (aNotify)
    1349               0 :         notifier.Notify();
    1350                 :     }
    1351               0 :     switch (newType) {
    1352                 :       case eType_Image:
    1353                 :         // Don't notify, because we will take care of that ourselves.
    1354               0 :         if (aURI) {
    1355               0 :           rv = LoadImage(aURI, aForceLoad, false);
    1356                 :         } else {
    1357               0 :           rv = NS_ERROR_NOT_AVAILABLE;
    1358                 :         }
    1359               0 :         break;
    1360                 :       case eType_Plugin:
    1361               0 :         rv = AsyncStartPluginInstance();
    1362               0 :         break;
    1363                 :       case eType_Document:
    1364               0 :         if (aURI) {
    1365               0 :           rv = mFrameLoader->LoadURI(aURI);
    1366                 :         } else {
    1367               0 :           rv = NS_ERROR_NOT_AVAILABLE;
    1368                 :         }
    1369               0 :         break;
    1370                 :       case eType_Loading:
    1371               0 :         NS_NOTREACHED("Should not have a loading type here!");
    1372                 :       case eType_Null:
    1373                 :         // No need to load anything, notify of the failure.
    1374               0 :         UpdateFallbackState(thisContent, fallback, aTypeHint);
    1375               0 :         break;
    1376                 :     };
    1377               0 :     return NS_OK;
    1378                 :   }
    1379                 : 
    1380                 :   // If the class ID specifies a supported plugin, or if we have no explicit URI
    1381                 :   // but a type, immediately instantiate the plugin.
    1382               0 :   bool isSupportedClassID = false;
    1383               0 :   nsCAutoString typeForID; // Will be set iff isSupportedClassID == true
    1384               0 :   bool hasID = false;
    1385               0 :   if (caps & eSupportClassID) {
    1386               0 :     nsAutoString classid;
    1387               0 :     thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::classid, classid);
    1388               0 :     if (!classid.IsEmpty()) {
    1389               0 :       hasID = true;
    1390               0 :       isSupportedClassID = NS_SUCCEEDED(TypeForClassID(classid, typeForID));
    1391                 :     }
    1392                 :   }
    1393                 : 
    1394               0 :   if (hasID && !isSupportedClassID) {
    1395                 :     // We have a class ID and it's unsupported.  Fallback in that case.
    1396               0 :     rv = NS_ERROR_NOT_AVAILABLE;
    1397               0 :     return NS_OK;
    1398                 :   }
    1399                 : 
    1400               0 :   if (isSupportedClassID ||
    1401               0 :       (!aURI && !aTypeHint.IsEmpty() &&
    1402               0 :        GetTypeOfContent(aTypeHint) == eType_Plugin)) {
    1403                 :     // No URI, but we have a type. The plugin will handle the load.
    1404                 :     // Or: supported class id, plugin will handle the load.
    1405               0 :     mType = eType_Plugin;
    1406                 : 
    1407                 :     // At this point, the stored content type
    1408                 :     // must be equal to our type hint. Similar,
    1409                 :     // our URI must be the requested URI.
    1410                 :     // (->Equals would suffice, but == is cheaper
    1411                 :     // and handles NULL)
    1412               0 :     NS_ASSERTION(mContentType.Equals(aTypeHint), "mContentType wrong!");
    1413               0 :     NS_ASSERTION(mURI == aURI, "mURI wrong!");
    1414                 : 
    1415               0 :     if (isSupportedClassID) {
    1416                 :       // Use the classid's type
    1417               0 :       NS_ASSERTION(!typeForID.IsEmpty(), "Must have a real type!");
    1418               0 :       mContentType = typeForID;
    1419                 :       // XXX(biesi). The plugin instantiation code used to pass the base URI
    1420                 :       // here instead of the plugin URI for instantiation via class ID, so I
    1421                 :       // continue to do so. Why that is, no idea...
    1422               0 :       GetObjectBaseURI(thisContent, getter_AddRefs(mURI));
    1423               0 :       if (!mURI) {
    1424               0 :         mURI = aURI;
    1425                 :       }
    1426                 :     }
    1427                 : 
    1428                 :     // rv is references by a stack-based object, need to assign here
    1429               0 :     rv = AsyncStartPluginInstance();
    1430                 : 
    1431               0 :     return rv;
    1432                 :   }
    1433                 : 
    1434               0 :   if (!aURI) {
    1435                 :     // No URI and if we have got this far no enabled plugin supports the type
    1436               0 :     rv = NS_ERROR_NOT_AVAILABLE;
    1437                 : 
    1438                 :     // We should only notify the UI if there is at least a type to go on for
    1439                 :     // finding a plugin to use, unless it's a supported image or document type.
    1440               0 :     if (!aTypeHint.IsEmpty() && GetTypeOfContent(aTypeHint) == eType_Null) {
    1441               0 :       UpdateFallbackState(thisContent, fallback, aTypeHint);
    1442                 :     }
    1443                 : 
    1444               0 :     return NS_OK;
    1445                 :   }
    1446                 : 
    1447                 :   // E.g. mms://
    1448               0 :   if (!CanHandleURI(aURI)) {
    1449               0 :     if (aTypeHint.IsEmpty()) {
    1450               0 :       rv = NS_ERROR_NOT_AVAILABLE;
    1451               0 :       return NS_OK;
    1452                 :     }
    1453                 : 
    1454               0 :     if (NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) {
    1455               0 :       mType = eType_Plugin;
    1456                 :     } else {
    1457               0 :       rv = NS_ERROR_NOT_AVAILABLE;
    1458                 :       // No plugin to load, notify of the failure.
    1459               0 :       UpdateFallbackState(thisContent, fallback, aTypeHint);
    1460                 :     }
    1461                 : 
    1462               0 :     return NS_OK;
    1463                 :   }
    1464                 : 
    1465               0 :   nsCOMPtr<nsILoadGroup> group = doc->GetDocumentLoadGroup();
    1466               0 :   nsCOMPtr<nsIChannel> chan;
    1467               0 :   nsCOMPtr<nsIChannelPolicy> channelPolicy;
    1468               0 :   nsCOMPtr<nsIContentSecurityPolicy> csp;
    1469               0 :   rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
    1470               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1471               0 :   if (csp) {
    1472               0 :     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
    1473               0 :     channelPolicy->SetContentSecurityPolicy(csp);
    1474               0 :     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
    1475                 :   }
    1476               0 :   rv = NS_NewChannel(getter_AddRefs(chan), aURI, nsnull, group, this,
    1477                 :                      nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
    1478                 :                      nsIChannel::LOAD_CLASSIFY_URI,
    1479               0 :                      channelPolicy);
    1480               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1481                 : 
    1482                 :   // Referrer
    1483               0 :   nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
    1484               0 :   if (httpChan) {
    1485               0 :     httpChan->SetReferrer(doc->GetDocumentURI());
    1486                 :   }
    1487                 : 
    1488                 :   // MIME Type hint
    1489               0 :   if (!aTypeHint.IsEmpty()) {
    1490               0 :     nsCAutoString typeHint, dummy;
    1491               0 :     NS_ParseContentType(aTypeHint, typeHint, dummy);
    1492               0 :     if (!typeHint.IsEmpty()) {
    1493               0 :       chan->SetContentType(typeHint);
    1494                 :     }
    1495                 :   }
    1496                 : 
    1497                 :   // Set up the channel's principal and such, like nsDocShell::DoURILoad does
    1498               0 :   nsContentUtils::SetUpChannelOwner(thisContent->NodePrincipal(),
    1499               0 :                                     chan, aURI, true);
    1500                 : 
    1501               0 :   nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(chan);
    1502               0 :   if (scriptChannel) {
    1503                 :     // Allow execution against our context if the principals match
    1504               0 :     scriptChannel->
    1505               0 :       SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
    1506                 :   }
    1507                 : 
    1508                 :   // AsyncOpen can fail if a file does not exist.
    1509                 :   // Show fallback content in that case.
    1510               0 :   rv = chan->AsyncOpen(this, nsnull);
    1511               0 :   if (NS_SUCCEEDED(rv)) {
    1512               0 :     LOG(("OBJLC [%p]: Channel opened.\n", this));
    1513                 : 
    1514               0 :     mChannel = chan;
    1515               0 :     mType = eType_Loading;
    1516                 :   }
    1517               0 :   return NS_OK;
    1518                 : }
    1519                 : 
    1520                 : PRUint32
    1521               0 : nsObjectLoadingContent::GetCapabilities() const
    1522                 : {
    1523                 :   return eSupportImages |
    1524                 :          eSupportPlugins |
    1525                 :          eSupportDocuments |
    1526               0 :          eSupportSVG;
    1527                 : }
    1528                 : 
    1529                 : void
    1530               0 : nsObjectLoadingContent::Fallback(bool aNotify)
    1531                 : {
    1532               0 :   AutoNotifier notifier(this, aNotify);
    1533                 : 
    1534               0 :   UnloadContent();
    1535               0 : }
    1536                 : 
    1537                 : void
    1538               0 : nsObjectLoadingContent::RemovedFromDocument()
    1539                 : {
    1540               0 :   if (mFrameLoader) {
    1541                 :     // XXX This is very temporary and must go away
    1542               0 :     mFrameLoader->Destroy();
    1543               0 :     mFrameLoader = nsnull;
    1544                 : 
    1545                 :     // Clear the current URI, so that LoadObject doesn't think that we
    1546                 :     // have already loaded the content.
    1547               0 :     mURI = nsnull;
    1548                 :   }
    1549                 : 
    1550                 :   // When a plugin instance node is removed from the document we'll
    1551                 :   // let the plugin continue to run at least until we get back to
    1552                 :   // the event loop. If we get back to the event loop and the node
    1553                 :   // has still not been added back to the document then we stop
    1554                 :   // the plugin.
    1555               0 :   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1556               0 :   nsCOMPtr<nsIRunnable> event = new InDocCheckEvent(thisContent);
    1557                 : 
    1558               0 :   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
    1559               0 :   if (appShell) {
    1560               0 :     appShell->RunInStableState(event);
    1561                 :   }
    1562               0 : }
    1563                 : 
    1564                 : /* static */
    1565                 : void
    1566               0 : nsObjectLoadingContent::Traverse(nsObjectLoadingContent *tmp,
    1567                 :                                  nsCycleCollectionTraversalCallback &cb)
    1568                 : {
    1569               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameLoader");
    1570               0 :   cb.NoteXPCOMChild(static_cast<nsIFrameLoader*>(tmp->mFrameLoader));
    1571               0 : }
    1572                 : 
    1573                 : // <private>
    1574                 : /* static */ bool
    1575               0 : nsObjectLoadingContent::IsSuccessfulRequest(nsIRequest* aRequest)
    1576                 : {
    1577                 :   nsresult status;
    1578               0 :   nsresult rv = aRequest->GetStatus(&status);
    1579               0 :   if (NS_FAILED(rv) || NS_FAILED(status)) {
    1580               0 :     return false;
    1581                 :   }
    1582                 : 
    1583                 :   // This may still be an error page or somesuch
    1584               0 :   nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(aRequest));
    1585               0 :   if (httpChan) {
    1586                 :     bool success;
    1587               0 :     rv = httpChan->GetRequestSucceeded(&success);
    1588               0 :     if (NS_FAILED(rv) || !success) {
    1589               0 :       return false;
    1590                 :     }
    1591                 :   }
    1592                 : 
    1593                 :   // Otherwise, the request is successful
    1594               0 :   return true;
    1595                 : }
    1596                 : 
    1597                 : /* static */ bool
    1598               0 : nsObjectLoadingContent::CanHandleURI(nsIURI* aURI)
    1599                 : {
    1600               0 :   nsCAutoString scheme;
    1601               0 :   if (NS_FAILED(aURI->GetScheme(scheme))) {
    1602               0 :     return false;
    1603                 :   }
    1604                 : 
    1605               0 :   nsIIOService* ios = nsContentUtils::GetIOService();
    1606               0 :   if (!ios)
    1607               0 :     return false;
    1608                 :   
    1609               0 :   nsCOMPtr<nsIProtocolHandler> handler;
    1610               0 :   ios->GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
    1611               0 :   if (!handler) {
    1612               0 :     return false;
    1613                 :   }
    1614                 :   
    1615                 :   nsCOMPtr<nsIExternalProtocolHandler> extHandler =
    1616               0 :     do_QueryInterface(handler);
    1617                 :   // We can handle this URI if its protocol handler is not the external one
    1618               0 :   return extHandler == nsnull;
    1619                 : }
    1620                 : 
    1621                 : bool
    1622               0 : nsObjectLoadingContent::IsSupportedDocument(const nsCString& aMimeType)
    1623                 : {
    1624                 :   nsCOMPtr<nsIContent> thisContent = 
    1625               0 :     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1626               0 :   NS_ASSERTION(thisContent, "must be a content");
    1627                 : 
    1628                 :   nsresult rv;
    1629                 :   nsCOMPtr<nsIWebNavigationInfo> info(
    1630               0 :     do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv));
    1631                 :   PRUint32 supported;
    1632               0 :   if (info) {
    1633               0 :     nsCOMPtr<nsIWebNavigation> webNav;
    1634               0 :     nsIDocument* currentDoc = thisContent->GetCurrentDoc();
    1635               0 :     if (currentDoc) {
    1636               0 :       webNav = do_GetInterface(currentDoc->GetScriptGlobalObject());
    1637                 :     }
    1638               0 :     rv = info->IsTypeSupported(aMimeType, webNav, &supported);
    1639                 :   }
    1640                 : 
    1641               0 :   if (NS_SUCCEEDED(rv)) {
    1642               0 :     if (supported == nsIWebNavigationInfo::UNSUPPORTED) {
    1643                 :       // Try a stream converter
    1644                 :       // NOTE: We treat any type we can convert from as a supported type. If a
    1645                 :       // type is not actually supported, the URI loader will detect that and
    1646                 :       // return an error, and we'll fallback.
    1647                 :       nsCOMPtr<nsIStreamConverterService> convServ =
    1648               0 :         do_GetService("@mozilla.org/streamConverters;1");
    1649               0 :       bool canConvert = false;
    1650               0 :       if (convServ) {
    1651               0 :         rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
    1652                 :       }
    1653                 : 
    1654               0 :       return NS_SUCCEEDED(rv) && canConvert;
    1655                 :     }
    1656                 : 
    1657                 :     // Don't want to support plugins as documents
    1658               0 :     return supported != nsIWebNavigationInfo::PLUGIN;
    1659                 :   }
    1660                 : 
    1661               0 :   return false;
    1662                 : }
    1663                 : 
    1664                 : void
    1665               0 : nsObjectLoadingContent::UnloadContent()
    1666                 : {
    1667                 :   // Don't notify in CancelImageRequests. We do it ourselves.
    1668               0 :   CancelImageRequests(false);
    1669               0 :   if (mFrameLoader) {
    1670               0 :     mFrameLoader->Destroy();
    1671               0 :     mFrameLoader = nsnull;
    1672                 :   }
    1673               0 :   mType = eType_Null;
    1674               0 :   mUserDisabled = mSuppressed = false;
    1675               0 :   mFallbackReason = ePluginOtherState;
    1676               0 : }
    1677                 : 
    1678                 : void
    1679               0 : nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
    1680                 :                                            nsEventStates aOldState,
    1681                 :                                            bool aSync,
    1682                 :                                            bool aNotify)
    1683                 : {
    1684               0 :   LOG(("OBJLC [%p]: Notifying about state change: (%u, %llx) -> (%u, %llx) (sync=%i)\n",
    1685                 :        this, aOldType, aOldState.GetInternalValue(), mType,
    1686                 :        ObjectState().GetInternalValue(), aSync));
    1687                 : 
    1688                 :   nsCOMPtr<nsIContent> thisContent = 
    1689               0 :     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1690               0 :   NS_ASSERTION(thisContent, "must be a content");
    1691                 : 
    1692               0 :   NS_ASSERTION(thisContent->IsElement(), "Not an element?");
    1693                 : 
    1694                 :   // Unfortunately, we do some state changes without notifying
    1695                 :   // (e.g. in Fallback when canceling image requests), so we have to
    1696                 :   // manually notify object state changes.
    1697               0 :   thisContent->AsElement()->UpdateState(false);
    1698                 : 
    1699               0 :   if (!aNotify) {
    1700                 :     // We're done here
    1701                 :     return;
    1702                 :   }
    1703                 : 
    1704               0 :   nsIDocument* doc = thisContent->GetCurrentDoc();
    1705               0 :   if (!doc) {
    1706                 :     return; // Nothing to do
    1707                 :   }
    1708                 : 
    1709               0 :   nsEventStates newState = ObjectState();
    1710                 : 
    1711               0 :   if (newState != aOldState) {
    1712                 :     // This will trigger frame construction
    1713               0 :     NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
    1714               0 :     nsEventStates changedBits = aOldState ^ newState;
    1715                 : 
    1716                 :     {
    1717               0 :       nsAutoScriptBlocker scriptBlocker;
    1718               0 :       doc->ContentStateChanged(thisContent, changedBits);
    1719                 :     }
    1720               0 :     if (aSync) {
    1721                 :       // Make sure that frames are actually constructed immediately.
    1722               0 :       doc->FlushPendingNotifications(Flush_Frames);
    1723                 :     }
    1724               0 :   } else if (aOldType != mType) {
    1725                 :     // If our state changed, then we already recreated frames
    1726                 :     // Otherwise, need to do that here
    1727               0 :     nsCOMPtr<nsIPresShell> shell = doc->GetShell();
    1728               0 :     if (shell) {
    1729               0 :       shell->RecreateFramesFor(thisContent);
    1730                 :     }
    1731                 :   }
    1732                 : }
    1733                 : 
    1734                 : /* static */ void
    1735               0 : nsObjectLoadingContent::FirePluginError(nsIContent* thisContent,
    1736                 :                                         PluginSupportState state)
    1737                 : {
    1738               0 :   LOG(("OBJLC []: Dispatching nsPluginErrorEvent for content %p\n",
    1739                 :        thisContent));
    1740                 : 
    1741               0 :   nsCOMPtr<nsIRunnable> ev = new nsPluginErrorEvent(thisContent, state);
    1742               0 :   nsresult rv = NS_DispatchToCurrentThread(ev);
    1743               0 :   if (NS_FAILED(rv)) {
    1744               0 :     NS_WARNING("failed to dispatch nsPluginErrorEvent");
    1745                 :   }
    1746               0 : }
    1747                 : 
    1748                 : nsObjectLoadingContent::ObjectType
    1749               0 : nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType)
    1750                 : {
    1751               0 :   PRUint32 caps = GetCapabilities();
    1752                 : 
    1753               0 :   if ((caps & eSupportImages) && IsSupportedImage(aMIMEType)) {
    1754               0 :     return eType_Image;
    1755                 :   }
    1756                 : 
    1757               0 :   bool isSVG = aMIMEType.LowerCaseEqualsLiteral("image/svg+xml");
    1758               0 :   bool supportedSVG = isSVG && (caps & eSupportSVG);
    1759               0 :   if (((caps & eSupportDocuments) || supportedSVG) &&
    1760               0 :       IsSupportedDocument(aMIMEType)) {
    1761               0 :     return eType_Document;
    1762                 :   }
    1763                 : 
    1764               0 :   if ((caps & eSupportPlugins) && NS_SUCCEEDED(IsPluginEnabledForType(aMIMEType))) {
    1765               0 :     return eType_Plugin;
    1766                 :   }
    1767                 : 
    1768               0 :   return eType_Null;
    1769                 : }
    1770                 : 
    1771                 : nsresult
    1772               0 : nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
    1773                 :                                        nsACString& aType)
    1774                 : {
    1775               0 :   if (StringBeginsWith(aClassID, NS_LITERAL_STRING("java:"))) {
    1776                 :     // Supported if we have a java plugin
    1777               0 :     aType.AssignLiteral("application/x-java-vm");
    1778               0 :     nsresult rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
    1779               0 :     return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_NOT_AVAILABLE;
    1780                 :   }
    1781                 : 
    1782                 :   // If it starts with "clsid:", this is ActiveX content
    1783               0 :   if (StringBeginsWith(aClassID, NS_LITERAL_STRING("clsid:"), nsCaseInsensitiveStringComparator())) {
    1784                 :     // Check if we have a plugin for that
    1785                 : 
    1786               0 :     if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-oleobject")))) {
    1787               0 :       aType.AssignLiteral("application/x-oleobject");
    1788               0 :       return NS_OK;
    1789                 :     }
    1790               0 :     if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/oleobject")))) {
    1791               0 :       aType.AssignLiteral("application/oleobject");
    1792               0 :       return NS_OK;
    1793                 :     }
    1794                 :   }
    1795                 : 
    1796               0 :   return NS_ERROR_NOT_AVAILABLE;
    1797                 : }
    1798                 : 
    1799                 : void
    1800               0 : nsObjectLoadingContent::GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI)
    1801                 : {
    1802                 :   // We want to use swap(); since this is just called from this file,
    1803                 :   // we can assert this (callers use comptrs)
    1804               0 :   NS_PRECONDITION(*aURI == nsnull, "URI must be inited to zero");
    1805                 : 
    1806                 :   // For plugins, the codebase attribute is the base URI
    1807               0 :   nsCOMPtr<nsIURI> baseURI = thisContent->GetBaseURI();
    1808               0 :   nsAutoString codebase;
    1809                 :   thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase,
    1810               0 :                        codebase);
    1811               0 :   if (!codebase.IsEmpty()) {
    1812                 :     nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
    1813                 :                                               thisContent->OwnerDoc(),
    1814               0 :                                               baseURI);
    1815                 :   } else {
    1816               0 :     baseURI.swap(*aURI);
    1817                 :   }
    1818               0 : }
    1819                 : 
    1820                 : nsObjectFrame*
    1821               0 : nsObjectLoadingContent::GetExistingFrame()
    1822                 : {
    1823               0 :   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1824               0 :   nsIFrame* frame = thisContent->GetPrimaryFrame();
    1825               0 :   nsIObjectFrame* objFrame = do_QueryFrame(frame);
    1826               0 :   return static_cast<nsObjectFrame*>(objFrame);
    1827                 : }
    1828                 : 
    1829                 : void
    1830               0 : nsObjectLoadingContent::HandleBeingBlockedByContentPolicy(nsresult aStatus,
    1831                 :                                                           PRInt16 aRetval)
    1832                 : {
    1833                 :   // Must call UnloadContent first, as it overwrites
    1834                 :   // mSuppressed/mUserDisabled. It also takes care of setting the type to
    1835                 :   // eType_Null.
    1836               0 :   UnloadContent();
    1837               0 :   if (NS_SUCCEEDED(aStatus)) {
    1838               0 :     if (aRetval == nsIContentPolicy::REJECT_TYPE) {
    1839               0 :       mUserDisabled = true;
    1840               0 :     } else if (aRetval == nsIContentPolicy::REJECT_SERVER) {
    1841               0 :       mSuppressed = true;
    1842                 :     }
    1843                 :   }
    1844               0 : }
    1845                 : 
    1846                 : PluginSupportState
    1847               0 : nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
    1848                 :                                               const nsCString& aContentType)
    1849                 : {
    1850               0 :   if (!aContent->IsHTML()) {
    1851               0 :     return ePluginOtherState;
    1852                 :   }
    1853                 : 
    1854               0 :   if (aContent->Tag() == nsGkAtoms::embed ||
    1855               0 :       aContent->Tag() == nsGkAtoms::applet) {
    1856               0 :     return GetPluginDisabledState(aContentType);
    1857                 :   }
    1858                 : 
    1859               0 :   bool hasAlternateContent = false;
    1860                 : 
    1861                 :   // Search for a child <param> with a pluginurl name
    1862               0 :   for (nsIContent* child = aContent->GetFirstChild();
    1863                 :        child;
    1864               0 :        child = child->GetNextSibling()) {
    1865               0 :     if (child->IsHTML(nsGkAtoms::param)) {
    1866               0 :       if (child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
    1867               0 :                              NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) {
    1868               0 :         return GetPluginDisabledState(aContentType);
    1869                 :       }
    1870               0 :     } else if (!hasAlternateContent) {
    1871                 :       hasAlternateContent =
    1872               0 :         nsStyleUtil::IsSignificantChild(child, true, false);
    1873                 :     }
    1874                 :   }
    1875                 : 
    1876                 :   return hasAlternateContent ? ePluginOtherState :
    1877               0 :     GetPluginDisabledState(aContentType);
    1878                 : }
    1879                 : 
    1880                 : PluginSupportState
    1881               0 : nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
    1882                 : {
    1883               0 :   nsresult rv = IsPluginEnabledForType(aContentType);
    1884               0 :   if (rv == NS_ERROR_PLUGIN_DISABLED)
    1885               0 :     return ePluginDisabled;
    1886               0 :   if (rv == NS_ERROR_PLUGIN_CLICKTOPLAY)
    1887               0 :     return ePluginClickToPlay;
    1888               0 :   if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
    1889               0 :     return ePluginBlocklisted;
    1890               0 :   return ePluginUnsupported;
    1891                 : }
    1892                 : 
    1893                 : void
    1894               0 : nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
    1895                 : {
    1896               0 :   nsImageLoadingContent::CreateStaticImageClone(aDest);
    1897                 : 
    1898               0 :   aDest->mType = mType;
    1899               0 :   nsObjectLoadingContent* thisObj = const_cast<nsObjectLoadingContent*>(this);
    1900               0 :   if (thisObj->mPrintFrame.IsAlive()) {
    1901               0 :     aDest->mPrintFrame = thisObj->mPrintFrame;
    1902                 :   } else {
    1903               0 :     aDest->mPrintFrame = const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame();
    1904                 :   }
    1905                 : 
    1906               0 :   if (mFrameLoader) {
    1907                 :     nsCOMPtr<nsIContent> content =
    1908               0 :       do_QueryInterface(static_cast<nsIImageLoadingContent*>(aDest));
    1909               0 :     nsFrameLoader* fl = nsFrameLoader::Create(content->AsElement(), false);
    1910               0 :     if (fl) {
    1911               0 :       aDest->mFrameLoader = fl;
    1912               0 :       mFrameLoader->CreateStaticClone(fl);
    1913                 :     }
    1914                 :   }
    1915               0 : }
    1916                 : 
    1917                 : NS_IMETHODIMP
    1918               0 : nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame)
    1919                 : {
    1920               0 :   *aFrame = mPrintFrame.GetFrame();
    1921               0 :   return NS_OK;
    1922                 : }
    1923                 : 
    1924                 : NS_IMETHODIMP
    1925               0 : nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
    1926                 :                                       const nsAString& pluginDumpID,
    1927                 :                                       const nsAString& browserDumpID,
    1928                 :                                       bool submittedCrashReport)
    1929                 : {
    1930               0 :   AutoNotifier notifier(this, true);
    1931               0 :   UnloadContent();
    1932               0 :   mFallbackReason = ePluginCrashed;
    1933               0 :   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1934                 : 
    1935                 :   // Note that aPluginTag in invalidated after we're called, so copy 
    1936                 :   // out any data we need now.
    1937               0 :   nsCAutoString pluginName;
    1938               0 :   aPluginTag->GetName(pluginName);
    1939               0 :   nsCAutoString pluginFilename;
    1940               0 :   aPluginTag->GetFilename(pluginFilename);
    1941                 : 
    1942                 :   nsCOMPtr<nsIRunnable> ev = new nsPluginCrashedEvent(thisContent,
    1943                 :                                                       pluginDumpID,
    1944                 :                                                       browserDumpID,
    1945               0 :                                                       NS_ConvertUTF8toUTF16(pluginName),
    1946               0 :                                                       NS_ConvertUTF8toUTF16(pluginFilename),
    1947               0 :                                                       submittedCrashReport);
    1948               0 :   nsresult rv = NS_DispatchToCurrentThread(ev);
    1949               0 :   if (NS_FAILED(rv)) {
    1950               0 :     NS_WARNING("failed to dispatch nsPluginCrashedEvent");
    1951                 :   }
    1952               0 :   return NS_OK;
    1953                 : }
    1954                 : 
    1955                 : NS_IMETHODIMP
    1956               0 : nsObjectLoadingContent::SyncStartPluginInstance()
    1957                 : {
    1958               0 :   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
    1959                 :                "Must be able to run script in order to instantiate a plugin instance!");
    1960                 : 
    1961                 :   // Don't even attempt to start an instance unless the content is in
    1962                 :   // the document.
    1963                 :   nsCOMPtr<nsIContent> thisContent =
    1964               0 :     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1965               0 :   if (!thisContent->IsInDoc()) {
    1966               0 :     return NS_ERROR_FAILURE;
    1967                 :   }
    1968                 : 
    1969               0 :   nsCOMPtr<nsIURI> kungFuURIGrip(mURI);
    1970               0 :   nsCString contentType(mContentType);
    1971               0 :   return InstantiatePluginInstance(contentType.get(), mURI.get());
    1972                 : }
    1973                 : 
    1974                 : NS_IMETHODIMP
    1975               0 : nsObjectLoadingContent::AsyncStartPluginInstance()
    1976                 : {
    1977                 :   // OK to have an instance already.
    1978               0 :   if (mInstanceOwner) {
    1979               0 :     return NS_OK;
    1980                 :   }
    1981                 : 
    1982               0 :   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    1983               0 :   nsIDocument* doc = thisContent->OwnerDoc();
    1984               0 :   if (doc->IsStaticDocument() || doc->IsBeingUsedAsImage()) {
    1985               0 :     return NS_OK;
    1986                 :   }
    1987                 : 
    1988                 :   // We always start plugins on a runnable.
    1989                 :   // We don't want a script blocker on the stack during instantiation.
    1990               0 :   nsCOMPtr<nsIRunnable> event = new nsAsyncInstantiateEvent(this);
    1991               0 :   if (!event) {
    1992               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1993                 :   }
    1994               0 :   nsresult rv = NS_DispatchToCurrentThread(event);
    1995               0 :   if (NS_SUCCEEDED(rv)) {
    1996                 :     // Remember this event.  This is a weak reference that will be cleared
    1997                 :     // when the event runs.
    1998               0 :     mPendingInstantiateEvent = event;
    1999                 :   }
    2000                 : 
    2001               0 :   return rv;
    2002                 : }
    2003                 : 
    2004                 : NS_IMETHODIMP
    2005               0 : nsObjectLoadingContent::GetSrcURI(nsIURI** aURI)
    2006                 : {
    2007               0 :   NS_IF_ADDREF(*aURI = mURI);
    2008               0 :   return NS_OK;
    2009                 : }
    2010                 : 
    2011                 : static bool
    2012               0 : DoDelayedStop(nsPluginInstanceOwner* aInstanceOwner,
    2013                 :               nsObjectLoadingContent* aContent,
    2014                 :               bool aDelayedStop)
    2015                 : {
    2016                 : #if (MOZ_PLATFORM_MAEMO==5)
    2017                 :   // Don't delay stop on Maemo/Hildon (bug 530739).
    2018                 :   if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash"))
    2019                 :     return false;
    2020                 : #endif
    2021                 :   
    2022                 :   // Don't delay stopping QuickTime (bug 425157), Flip4Mac (bug 426524),
    2023                 :   // XStandard (bug 430219), CMISS Zinc (bug 429604).
    2024               0 :   if (aDelayedStop
    2025                 : #if !(defined XP_WIN || defined MOZ_X11)
    2026                 :       && !aInstanceOwner->MatchPluginName("QuickTime")
    2027                 :       && !aInstanceOwner->MatchPluginName("Flip4Mac")
    2028                 :       && !aInstanceOwner->MatchPluginName("XStandard plugin")
    2029                 :       && !aInstanceOwner->MatchPluginName("CMISS Zinc Plugin")
    2030                 : #endif
    2031                 :       ) {
    2032                 :     nsCOMPtr<nsIRunnable> evt =
    2033               0 :       new nsStopPluginRunnable(aInstanceOwner, aContent);
    2034               0 :     NS_DispatchToCurrentThread(evt);
    2035               0 :     return true;
    2036                 :   }
    2037               0 :   return false;
    2038                 : }
    2039                 : 
    2040                 : void
    2041               0 : nsObjectLoadingContent::DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner,
    2042                 :                                      bool aDelayedStop,
    2043                 :                                      bool aForcedReentry)
    2044                 : {
    2045                 :   // DoStopPlugin can process events and there may be pending InDocCheckEvent
    2046                 :   // events which can drop in underneath us and destroy the instance we are
    2047                 :   // about to destroy unless we prevent that with the mIsStopping flag.
    2048                 :   // (aForcedReentry is only true from the callback of an earlier delayed stop)
    2049               0 :   if (mIsStopping && !aForcedReentry) {
    2050               0 :     return;
    2051                 :   }
    2052               0 :   mIsStopping = true;
    2053                 : 
    2054               0 :   nsRefPtr<nsPluginInstanceOwner> kungFuDeathGrip(aInstanceOwner);
    2055               0 :   nsRefPtr<nsNPAPIPluginInstance> inst;
    2056               0 :   aInstanceOwner->GetInstance(getter_AddRefs(inst));
    2057               0 :   if (inst) {
    2058               0 :     if (DoDelayedStop(aInstanceOwner, this, aDelayedStop)) {
    2059                 :       return;
    2060                 :     }
    2061                 : 
    2062                 : #if defined(XP_MACOSX)
    2063                 :     aInstanceOwner->HidePluginWindow();
    2064                 : #endif
    2065                 : 
    2066               0 :     nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
    2067               0 :     NS_ASSERTION(pluginHost, "Without a pluginHost, how can we have an instance to destroy?");
    2068               0 :     static_cast<nsPluginHost*>(pluginHost.get())->StopPluginInstance(inst);
    2069                 :   }
    2070                 :   
    2071               0 :   aInstanceOwner->Destroy();
    2072               0 :   mIsStopping = false;
    2073                 : }
    2074                 : 
    2075                 : NS_IMETHODIMP
    2076               0 : nsObjectLoadingContent::StopPluginInstance()
    2077                 : {
    2078               0 :   if (!mInstanceOwner) {
    2079               0 :     return NS_OK;
    2080                 :   }
    2081                 : 
    2082               0 :   DisconnectFrame();
    2083                 : 
    2084               0 :   bool delayedStop = false;
    2085                 : #ifdef XP_WIN
    2086                 :   // Force delayed stop for Real plugin only; see bug 420886, 426852.
    2087                 :   nsRefPtr<nsNPAPIPluginInstance> inst;
    2088                 :   mInstanceOwner->GetInstance(getter_AddRefs(inst));
    2089                 :   if (inst) {
    2090                 :     const char* mime = nsnull;
    2091                 :     if (NS_SUCCEEDED(inst->GetMIMEType(&mime)) && mime) {
    2092                 :       if (strcmp(mime, "audio/x-pn-realaudio-plugin") == 0) {
    2093                 :         delayedStop = true;
    2094                 :       }      
    2095                 :     }
    2096                 :   }
    2097                 : #endif
    2098                 : 
    2099               0 :   DoStopPlugin(mInstanceOwner, delayedStop);
    2100                 : 
    2101               0 :   mInstanceOwner = nsnull;
    2102                 : 
    2103               0 :   return NS_OK;
    2104                 : }
    2105                 : 
    2106                 : void
    2107               0 : nsObjectLoadingContent::NotifyContentObjectWrapper()
    2108                 : {
    2109               0 :   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
    2110                 : 
    2111               0 :   nsCOMPtr<nsIDocument> doc = thisContent->GetDocument();
    2112               0 :   if (!doc)
    2113                 :     return;
    2114                 :   
    2115               0 :   nsIScriptGlobalObject *sgo = doc->GetScopeObject();
    2116               0 :   if (!sgo)
    2117                 :     return;
    2118                 :   
    2119               0 :   nsIScriptContext *scx = sgo->GetContext();
    2120               0 :   if (!scx)
    2121                 :     return;
    2122                 :   
    2123               0 :   JSContext *cx = scx->GetNativeContext();
    2124                 :   
    2125               0 :   nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
    2126               0 :   nsContentUtils::XPConnect()->
    2127               0 :   GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), thisContent,
    2128                 :                                  NS_GET_IID(nsISupports),
    2129               0 :                                  getter_AddRefs(wrapper));
    2130                 :   
    2131               0 :   if (!wrapper) {
    2132                 :     // Nothing to do here if there's no wrapper for mContent. The proto
    2133                 :     // chain will be fixed appropriately when the wrapper is created.
    2134                 :     return;
    2135                 :   }
    2136                 :   
    2137               0 :   JSObject *obj = nsnull;
    2138               0 :   nsresult rv = wrapper->GetJSObject(&obj);
    2139               0 :   if (NS_FAILED(rv))
    2140                 :     return;
    2141                 :   
    2142               0 :   nsHTMLPluginObjElementSH::SetupProtoChain(wrapper, cx, obj);
    2143                 : }
    2144                 : 
    2145                 : NS_IMETHODIMP
    2146               0 : nsObjectLoadingContent::PlayPlugin()
    2147                 : {
    2148               0 :   if (!nsContentUtils::IsCallerChrome())
    2149               0 :     return NS_OK;
    2150                 : 
    2151               0 :   mShouldPlay = true;
    2152               0 :   return LoadObject(mURI, true, mContentType, true);
    2153            4392 : }

Generated by: LCOV version 1.7