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

Generated by: LCOV version 1.7