2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
// vim:set et cin sw=2 sts=2:
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
/*
|
2007-07-18 14:48:18 -07:00
|
|
|
* A base class implementing nsIObjectLoadingContent for use by
|
2007-03-22 10:30:00 -07:00
|
|
|
* various content nodes that want to provide plugin/document/image
|
|
|
|
* loading functionality (eg <embed>, <object>, <applet>, etc).
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Interface headers
|
|
|
|
#include "imgILoader.h"
|
2010-02-09 17:05:31 -08:00
|
|
|
#include "nsEventDispatcher.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIDocument.h"
|
2010-02-09 17:05:31 -08:00
|
|
|
#include "nsIDOMDataContainerEvent.h"
|
2011-05-23 09:46:36 -07:00
|
|
|
#include "nsIDOMDocument.h"
|
2010-02-09 17:05:31 -08:00
|
|
|
#include "nsIDOMEventTarget.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIExternalProtocolHandler.h"
|
2011-04-21 10:35:52 -07:00
|
|
|
#include "nsEventStates.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIObjectFrame.h"
|
|
|
|
#include "nsIPluginDocument.h"
|
2012-04-18 11:40:55 -07:00
|
|
|
#include "nsIPermissionManager.h"
|
2011-05-17 18:48:34 -07:00
|
|
|
#include "nsPluginHost.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
#include "nsIStreamConverterService.h"
|
|
|
|
#include "nsIURILoader.h"
|
|
|
|
#include "nsIURL.h"
|
|
|
|
#include "nsIWebNavigation.h"
|
|
|
|
#include "nsIWebNavigationInfo.h"
|
2007-12-03 13:57:17 -08:00
|
|
|
#include "nsIScriptChannel.h"
|
2009-10-02 04:26:04 -07:00
|
|
|
#include "nsIBlocklistService.h"
|
2010-08-04 19:15:55 -07:00
|
|
|
#include "nsIAsyncVerifyRedirectCallback.h"
|
2012-01-31 13:55:54 -08:00
|
|
|
#include "nsIAppShell.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "nsPluginError.h"
|
|
|
|
|
|
|
|
// Util headers
|
|
|
|
#include "prlog.h"
|
|
|
|
|
|
|
|
#include "nsAutoPtr.h"
|
|
|
|
#include "nsCURILoader.h"
|
|
|
|
#include "nsContentPolicyUtils.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsDocShellCID.h"
|
|
|
|
#include "nsGkAtoms.h"
|
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include "nsNetUtil.h"
|
2007-08-20 20:26:12 -07:00
|
|
|
#include "nsMimeTypes.h"
|
2008-03-26 16:04:57 -07:00
|
|
|
#include "nsStyleUtil.h"
|
2010-02-09 17:05:31 -08:00
|
|
|
#include "nsGUIEvent.h"
|
2011-02-08 05:35:25 -08:00
|
|
|
#include "nsUnicharUtils.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Concrete classes
|
|
|
|
#include "nsFrameLoader.h"
|
|
|
|
|
|
|
|
#include "nsObjectLoadingContent.h"
|
2008-04-11 10:29:06 -07:00
|
|
|
#include "mozAutoDocUpdate.h"
|
2010-04-23 12:51:25 -07:00
|
|
|
#include "nsIContentSecurityPolicy.h"
|
|
|
|
#include "nsIChannelPolicy.h"
|
|
|
|
#include "nsChannelPolicy.h"
|
2011-07-20 12:18:54 -07:00
|
|
|
#include "mozilla/dom/Element.h"
|
2012-01-18 16:53:35 -08:00
|
|
|
#include "sampler.h"
|
2012-01-31 13:55:54 -08:00
|
|
|
#include "nsObjectFrame.h"
|
|
|
|
#include "nsDOMClassInfo.h"
|
|
|
|
|
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
#include "nsContentCID.h"
|
|
|
|
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
|
|
|
|
#define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
|
|
|
|
|
|
|
|
class nsAsyncInstantiateEvent : public nsRunnable {
|
|
|
|
public:
|
2012-07-25 13:39:01 -07:00
|
|
|
nsObjectLoadingContent *mContent;
|
|
|
|
nsAsyncInstantiateEvent(nsObjectLoadingContent* aContent)
|
|
|
|
: mContent(aContent)
|
|
|
|
{
|
|
|
|
static_cast<nsIObjectLoadingContent *>(mContent)->AddRef();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
~nsAsyncInstantiateEvent()
|
|
|
|
{
|
|
|
|
static_cast<nsIObjectLoadingContent *>(mContent)->Release();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_IMETHOD Run();
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsAsyncInstantiateEvent::Run()
|
|
|
|
{
|
2012-01-31 13:55:54 -08:00
|
|
|
// do nothing if we've been revoked
|
2012-07-25 13:39:01 -07:00
|
|
|
if (mContent->mPendingInstantiateEvent != this) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
mContent->mPendingInstantiateEvent = nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
return mContent->SyncStartPluginInstance();
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
2011-08-29 00:09:22 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
// Checks to see if the content for a plugin instance has a parent.
|
|
|
|
// The plugin instance is stopped if there is no parent.
|
|
|
|
class InDocCheckEvent : public nsRunnable {
|
|
|
|
public:
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> mContent;
|
2011-08-29 23:09:56 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
InDocCheckEvent(nsIContent* aContent)
|
|
|
|
: mContent(aContent)
|
|
|
|
{
|
|
|
|
}
|
2012-01-31 13:55:54 -08:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
~InDocCheckEvent()
|
|
|
|
{
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
NS_IMETHOD Run();
|
2012-01-31 13:55:54 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
InDocCheckEvent::Run()
|
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!mContent->IsInDoc()) {
|
|
|
|
nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(mContent);
|
|
|
|
if (olc) {
|
|
|
|
olc->StopPluginInstance();
|
|
|
|
}
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2007-07-13 17:28:05 -07:00
|
|
|
* A task for firing PluginNotFound and PluginBlocklisted DOM Events.
|
2007-03-22 10:30:00 -07:00
|
|
|
*/
|
2007-07-13 17:28:05 -07:00
|
|
|
class nsPluginErrorEvent : public nsRunnable {
|
2007-03-22 10:30:00 -07:00
|
|
|
public:
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> mContent;
|
|
|
|
PluginSupportState mState;
|
|
|
|
|
|
|
|
nsPluginErrorEvent(nsIContent* aContent, PluginSupportState aState)
|
2007-07-13 17:28:05 -07:00
|
|
|
: mContent(aContent),
|
2012-07-25 13:39:01 -07:00
|
|
|
mState(aState)
|
|
|
|
{}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-07-13 17:28:05 -07:00
|
|
|
~nsPluginErrorEvent() {}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_IMETHOD Run();
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2007-07-13 17:28:05 -07:00
|
|
|
nsPluginErrorEvent::Run()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
LOG(("OBJLC []: Firing plugin not found event for content %p\n",
|
|
|
|
mContent.get()));
|
2008-09-09 08:43:21 -07:00
|
|
|
nsString type;
|
2012-07-25 13:39:01 -07:00
|
|
|
switch (mState) {
|
|
|
|
case ePluginClickToPlay:
|
|
|
|
type = NS_LITERAL_STRING("PluginClickToPlay");
|
|
|
|
break;
|
|
|
|
case ePluginVulnerableUpdatable:
|
2012-07-11 08:56:34 -07:00
|
|
|
type = NS_LITERAL_STRING("PluginVulnerableUpdatable");
|
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginVulnerableNoUpdate:
|
2012-07-11 08:56:34 -07:00
|
|
|
type = NS_LITERAL_STRING("PluginVulnerableNoUpdate");
|
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginUnsupported:
|
2008-09-09 08:43:21 -07:00
|
|
|
type = NS_LITERAL_STRING("PluginNotFound");
|
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginDisabled:
|
2008-09-09 08:43:21 -07:00
|
|
|
type = NS_LITERAL_STRING("PluginDisabled");
|
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginBlocklisted:
|
2008-09-09 08:43:21 -07:00
|
|
|
type = NS_LITERAL_STRING("PluginBlocklisted");
|
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginOutdated:
|
2009-10-02 04:26:04 -07:00
|
|
|
type = NS_LITERAL_STRING("PluginOutdated");
|
|
|
|
break;
|
2008-09-09 08:43:21 -07:00
|
|
|
default:
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
|
2011-10-17 07:59:28 -07:00
|
|
|
type, true, true);
|
2007-07-13 17:28:05 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-02-09 17:05:31 -08:00
|
|
|
/**
|
|
|
|
* A task for firing PluginCrashed DOM Events.
|
|
|
|
*/
|
|
|
|
class nsPluginCrashedEvent : public nsRunnable {
|
|
|
|
public:
|
|
|
|
nsCOMPtr<nsIContent> mContent;
|
2010-03-24 14:22:04 -07:00
|
|
|
nsString mPluginDumpID;
|
|
|
|
nsString mBrowserDumpID;
|
2010-02-09 17:05:31 -08:00
|
|
|
nsString mPluginName;
|
2010-04-08 00:45:00 -07:00
|
|
|
nsString mPluginFilename;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool mSubmittedCrashReport;
|
2010-02-09 17:05:31 -08:00
|
|
|
|
|
|
|
nsPluginCrashedEvent(nsIContent* aContent,
|
2010-03-24 14:22:04 -07:00
|
|
|
const nsAString& aPluginDumpID,
|
|
|
|
const nsAString& aBrowserDumpID,
|
2010-02-09 17:05:31 -08:00
|
|
|
const nsAString& aPluginName,
|
2010-04-08 00:45:00 -07:00
|
|
|
const nsAString& aPluginFilename,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool submittedCrashReport)
|
2010-02-09 17:05:31 -08:00
|
|
|
: mContent(aContent),
|
2010-03-24 14:22:04 -07:00
|
|
|
mPluginDumpID(aPluginDumpID),
|
|
|
|
mBrowserDumpID(aBrowserDumpID),
|
2010-02-09 17:05:31 -08:00
|
|
|
mPluginName(aPluginName),
|
2010-04-08 00:45:00 -07:00
|
|
|
mPluginFilename(aPluginFilename),
|
2010-02-09 17:05:31 -08:00
|
|
|
mSubmittedCrashReport(submittedCrashReport)
|
|
|
|
{}
|
|
|
|
|
|
|
|
~nsPluginCrashedEvent() {}
|
|
|
|
|
|
|
|
NS_IMETHOD Run();
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPluginCrashedEvent::Run()
|
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
LOG(("OBJLC []: Firing plugin crashed event for content %p\n",
|
2010-02-09 17:05:31 -08:00
|
|
|
mContent.get()));
|
|
|
|
|
2011-05-23 09:46:36 -07:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc =
|
2010-02-09 17:05:31 -08:00
|
|
|
do_QueryInterface(mContent->GetDocument());
|
2011-05-23 09:46:36 -07:00
|
|
|
if (!domDoc) {
|
2010-02-09 17:05:31 -08:00
|
|
|
NS_WARNING("Couldn't get document for PluginCrashed event!");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
2011-05-23 09:46:36 -07:00
|
|
|
domDoc->CreateEvent(NS_LITERAL_STRING("datacontainerevents"),
|
|
|
|
getter_AddRefs(event));
|
2010-02-09 17:05:31 -08:00
|
|
|
nsCOMPtr<nsIDOMDataContainerEvent> containerEvent(do_QueryInterface(event));
|
2012-06-10 11:14:30 -07:00
|
|
|
if (!containerEvent) {
|
2010-02-09 17:05:31 -08:00
|
|
|
NS_WARNING("Couldn't QI event for PluginCrashed event!");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
event->InitEvent(NS_LITERAL_STRING("PluginCrashed"), true, true);
|
2012-06-10 11:14:30 -07:00
|
|
|
event->SetTrusted(true);
|
|
|
|
event->GetInternalNSEvent()->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH;
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2010-02-09 17:05:31 -08:00
|
|
|
nsCOMPtr<nsIWritableVariant> variant;
|
|
|
|
|
2010-03-24 14:22:04 -07:00
|
|
|
// add a "pluginDumpID" property to this event
|
2010-03-16 22:10:08 -07:00
|
|
|
variant = do_CreateInstance("@mozilla.org/variant;1");
|
|
|
|
if (!variant) {
|
2010-03-24 14:22:04 -07:00
|
|
|
NS_WARNING("Couldn't create pluginDumpID variant for PluginCrashed event!");
|
2010-03-16 22:10:08 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-03-24 14:22:04 -07:00
|
|
|
variant->SetAsAString(mPluginDumpID);
|
|
|
|
containerEvent->SetData(NS_LITERAL_STRING("pluginDumpID"), variant);
|
|
|
|
|
|
|
|
// add a "browserDumpID" property to this event
|
|
|
|
variant = do_CreateInstance("@mozilla.org/variant;1");
|
|
|
|
if (!variant) {
|
|
|
|
NS_WARNING("Couldn't create browserDumpID variant for PluginCrashed event!");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
variant->SetAsAString(mBrowserDumpID);
|
|
|
|
containerEvent->SetData(NS_LITERAL_STRING("browserDumpID"), variant);
|
2010-03-16 22:10:08 -07:00
|
|
|
|
2010-02-09 17:05:31 -08:00
|
|
|
// add a "pluginName" property to this event
|
|
|
|
variant = do_CreateInstance("@mozilla.org/variant;1");
|
|
|
|
if (!variant) {
|
|
|
|
NS_WARNING("Couldn't create pluginName variant for PluginCrashed event!");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
variant->SetAsAString(mPluginName);
|
|
|
|
containerEvent->SetData(NS_LITERAL_STRING("pluginName"), variant);
|
|
|
|
|
2010-04-08 00:45:00 -07:00
|
|
|
// add a "pluginFilename" property to this event
|
|
|
|
variant = do_CreateInstance("@mozilla.org/variant;1");
|
|
|
|
if (!variant) {
|
|
|
|
NS_WARNING("Couldn't create pluginFilename variant for PluginCrashed event!");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
variant->SetAsAString(mPluginFilename);
|
|
|
|
containerEvent->SetData(NS_LITERAL_STRING("pluginFilename"), variant);
|
|
|
|
|
2010-02-09 17:05:31 -08:00
|
|
|
// add a "submittedCrashReport" property to this event
|
|
|
|
variant = do_CreateInstance("@mozilla.org/variant;1");
|
|
|
|
if (!variant) {
|
|
|
|
NS_WARNING("Couldn't create crashSubmit variant for PluginCrashed event!");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
variant->SetAsBool(mSubmittedCrashReport);
|
|
|
|
containerEvent->SetData(NS_LITERAL_STRING("submittedCrashReport"), variant);
|
|
|
|
|
|
|
|
nsEventDispatcher::DispatchDOMEvent(mContent, nsnull, event, nsnull, nsnull);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
class nsStopPluginRunnable : public nsRunnable, public nsITimerCallback
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
|
2012-05-25 15:34:11 -07:00
|
|
|
nsStopPluginRunnable(nsPluginInstanceOwner* aInstanceOwner,
|
|
|
|
nsObjectLoadingContent* aContent)
|
|
|
|
: mInstanceOwner(aInstanceOwner)
|
|
|
|
, mContent(aContent)
|
2012-01-31 13:55:54 -08:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aInstanceOwner, "need an owner");
|
2012-05-25 15:34:11 -07:00
|
|
|
NS_ASSERTION(aContent, "need a nsObjectLoadingContent");
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// nsRunnable
|
|
|
|
NS_IMETHOD Run();
|
|
|
|
|
|
|
|
// nsITimerCallback
|
|
|
|
NS_IMETHOD Notify(nsITimer *timer);
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsCOMPtr<nsITimer> mTimer;
|
|
|
|
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
2012-05-25 17:43:44 -07:00
|
|
|
nsCOMPtr<nsIObjectLoadingContent> mContent;
|
2012-01-31 13:55:54 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsStopPluginRunnable::Notify(nsITimer *aTimer)
|
|
|
|
{
|
|
|
|
return Run();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsStopPluginRunnable::Run()
|
|
|
|
{
|
|
|
|
// InitWithCallback calls Release before AddRef so we need to hold a
|
|
|
|
// strong ref on 'this' since we fall through to this scope if it fails.
|
|
|
|
nsCOMPtr<nsITimerCallback> kungFuDeathGrip = this;
|
|
|
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
|
|
|
if (appShell) {
|
|
|
|
PRUint32 currentLevel = 0;
|
|
|
|
appShell->GetEventloopNestingLevel(¤tLevel);
|
|
|
|
if (currentLevel > mInstanceOwner->GetLastEventloopNestingLevel()) {
|
|
|
|
if (!mTimer)
|
|
|
|
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
if (mTimer) {
|
|
|
|
// Fire 100ms timer to try to tear down this plugin as quickly as
|
|
|
|
// possible once the nesting level comes back down.
|
2012-07-25 13:39:01 -07:00
|
|
|
nsresult rv = mTimer->InitWithCallback(this, 100, nsITimer::TYPE_ONE_SHOT);
|
2012-01-31 13:55:54 -08:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_ERROR("Failed to setup a timer to stop the plugin later (at a safe "
|
|
|
|
"time). Stopping the plugin now, this might crash.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mTimer = nsnull;
|
|
|
|
|
2012-05-25 17:43:44 -07:00
|
|
|
static_cast<nsObjectLoadingContent*>(mContent.get())->
|
|
|
|
DoStopPlugin(mInstanceOwner, false, true);
|
2012-01-31 13:55:54 -08:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
class AutoNotifier {
|
|
|
|
public:
|
|
|
|
AutoNotifier(nsObjectLoadingContent* aContent, bool aNotify) :
|
|
|
|
mContent(aContent), mNotify(aNotify) {
|
|
|
|
mOldType = aContent->Type();
|
|
|
|
mOldState = aContent->ObjectState();
|
|
|
|
}
|
|
|
|
~AutoNotifier() {
|
|
|
|
mContent->NotifyStateChanged(mOldType, mOldState, false, mNotify);
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
/**
|
|
|
|
* Send notifications now, ignoring the value of mNotify. The new type and
|
|
|
|
* state is saved, and the destructor will notify again if mNotify is true
|
|
|
|
* and the values changed.
|
|
|
|
*/
|
|
|
|
void Notify() {
|
|
|
|
NS_ASSERTION(mNotify, "Should not notify when notify=false");
|
|
|
|
|
|
|
|
mContent->NotifyStateChanged(mOldType, mOldState, true, true);
|
|
|
|
mOldType = mContent->Type();
|
|
|
|
mOldState = mContent->ObjectState();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsObjectLoadingContent* mContent;
|
|
|
|
bool mNotify;
|
|
|
|
nsObjectLoadingContent::ObjectType mOldType;
|
|
|
|
nsEventStates mOldState;
|
2012-07-05 14:07:46 -07:00
|
|
|
};
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
/**
|
|
|
|
* A class that will automatically fall back if a |rv| variable has a failure
|
|
|
|
* code when this class is destroyed. It does not notify.
|
|
|
|
*/
|
|
|
|
class AutoFallback {
|
|
|
|
public:
|
|
|
|
AutoFallback(nsObjectLoadingContent* aContent, const nsresult* rv)
|
|
|
|
: mContent(aContent), mResult(rv), mPluginState(ePluginOtherState) {}
|
|
|
|
~AutoFallback() {
|
|
|
|
if (NS_FAILED(*mResult)) {
|
|
|
|
LOG(("OBJLC [%p]: rv=%08x, falling back\n", mContent, *mResult));
|
|
|
|
mContent->Fallback(false);
|
|
|
|
if (mPluginState != ePluginOtherState) {
|
|
|
|
mContent->mFallbackReason = mPluginState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This should be set to something other than ePluginOtherState to indicate
|
|
|
|
* a specific failure that should be passed on.
|
|
|
|
*/
|
|
|
|
void SetPluginState(PluginSupportState aState) {
|
|
|
|
NS_ASSERTION(aState != ePluginOtherState, "Should not be setting ePluginOtherState");
|
|
|
|
mPluginState = aState;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
nsObjectLoadingContent* mContent;
|
|
|
|
const nsresult* mResult;
|
|
|
|
PluginSupportState mPluginState;
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
/**
|
|
|
|
* A class that automatically sets mInstantiating to false when it goes
|
|
|
|
* out of scope.
|
|
|
|
*/
|
|
|
|
class AutoSetInstantiatingToFalse {
|
|
|
|
public:
|
|
|
|
AutoSetInstantiatingToFalse(nsObjectLoadingContent* objlc) : mContent(objlc) {}
|
|
|
|
~AutoSetInstantiatingToFalse() { mContent->mInstantiating = false; }
|
|
|
|
private:
|
|
|
|
nsObjectLoadingContent* mContent;
|
|
|
|
};
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// helper functions
|
2012-07-05 14:07:46 -07:00
|
|
|
static bool
|
2012-07-25 13:39:01 -07:00
|
|
|
IsSupportedImage(const nsCString& aMimeType)
|
2012-07-05 14:07:46 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
imgILoader* loader = nsContentUtils::GetImgLoader();
|
|
|
|
if (!loader) {
|
2012-07-05 14:07:46 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
bool supported;
|
|
|
|
nsresult rv = loader->SupportImageWithMimeType(aMimeType.get(), &supported);
|
|
|
|
return NS_SUCCEEDED(rv) && supported;
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMEType)
|
2012-07-05 14:07:46 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
|
|
|
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
|
|
|
if (!pluginHost) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get());
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Check to see if the plugin is disabled before deciding if it
|
|
|
|
// should be in the "click to play" state, since we only want to
|
|
|
|
// display "click to play" UI for enabled plugins.
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!pluginHost->IsPluginClickToPlayForType(aMIMEType.get())) {
|
|
|
|
mCTPPlayable = true;
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!mCTPPlayable) {
|
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
|
|
|
|
MOZ_ASSERT(thisContent);
|
|
|
|
nsIDocument* ownerDoc = thisContent->OwnerDoc();
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIDOMWindow> window = ownerDoc->GetWindow();
|
|
|
|
if (!window) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMWindow> topWindow;
|
|
|
|
rv = window->GetTop(getter_AddRefs(topWindow));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIDOMDocument> topDocument;
|
|
|
|
rv = topWindow->GetDocument(getter_AddRefs(topDocument));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDocument);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
bool allowPerm = false;
|
|
|
|
// For now we always say that the system principal uses click-to-play since
|
|
|
|
// that maintains current behavior and we have tests that expect this.
|
|
|
|
// What we really should do is disable plugins entirely in pages that use
|
|
|
|
// the system principal, i.e. in chrome pages. That way the click-to-play
|
|
|
|
// code here wouldn't matter at all. Bug 775301 is tracking this.
|
|
|
|
if (!nsContentUtils::IsSystemPrincipal(topDoc->NodePrincipal())) {
|
|
|
|
PRUint32 permission;
|
|
|
|
rv = permissionManager->TestPermissionFromPrincipal(topDoc->NodePrincipal(),
|
|
|
|
"plugins",
|
|
|
|
&permission);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
allowPerm = permission == nsIPermissionManager::ALLOW_ACTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32 state;
|
|
|
|
rv = pluginHost->GetBlocklistStateForType(aMIMEType.get(), &state);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (allowPerm &&
|
|
|
|
state != nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE &&
|
|
|
|
state != nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
|
|
|
|
mCTPPlayable = true;
|
|
|
|
} else {
|
|
|
|
return NS_ERROR_PLUGIN_CLICKTOPLAY;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-05 14:07:46 -07:00
|
|
|
static void
|
|
|
|
GetExtensionFromURI(nsIURI* uri, nsCString& ext)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
|
|
|
|
if (url) {
|
|
|
|
url->GetFileExtension(ext);
|
|
|
|
} else {
|
|
|
|
nsCString spec;
|
|
|
|
uri->GetSpec(spec);
|
|
|
|
|
|
|
|
PRInt32 offset = spec.RFindChar('.');
|
|
|
|
if (offset != kNotFound) {
|
|
|
|
ext = Substring(spec, offset + 1, spec.Length());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether a plugin exists and is enabled for the extension
|
|
|
|
* in the given URI. The MIME type is returned in the mimeType out parameter.
|
|
|
|
*/
|
2012-07-25 13:39:01 -07:00
|
|
|
bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-05 14:07:46 -07:00
|
|
|
nsCAutoString ext;
|
|
|
|
GetExtensionFromURI(uri, ext);
|
2012-07-25 13:39:01 -07:00
|
|
|
bool enabled = false;
|
2012-07-05 14:07:46 -07:00
|
|
|
|
|
|
|
if (ext.IsEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
|
|
|
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
2011-05-21 06:28:54 -07:00
|
|
|
if (!pluginHost) {
|
2012-07-05 14:07:46 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* typeFromExt;
|
2012-07-25 13:39:01 -07:00
|
|
|
if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
|
2012-07-05 14:07:46 -07:00
|
|
|
mimeType = typeFromExt;
|
2012-07-25 13:39:01 -07:00
|
|
|
enabled = true;
|
2012-07-05 13:47:39 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!pluginHost->IsPluginClickToPlayForType(mimeType.get())) {
|
|
|
|
mCTPPlayable = true;
|
2007-07-18 14:48:18 -07:00
|
|
|
}
|
|
|
|
}
|
2012-07-11 08:56:34 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!mCTPPlayable) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return enabled;
|
2007-07-18 14:48:18 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-28 08:53:56 -07:00
|
|
|
nsresult
|
2012-07-25 13:39:01 -07:00
|
|
|
nsObjectLoadingContent::BindToTree(nsIDocument* aDocument, nsIContent* /*aParent*/,
|
2012-03-28 08:53:56 -07:00
|
|
|
nsIContent* /*aBindingParent*/,
|
|
|
|
bool /*aCompileEventHandlers*/)
|
|
|
|
{
|
|
|
|
if (aDocument) {
|
|
|
|
return aDocument->AddPlugin(this);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectLoadingContent::UnbindFromTree(bool /*aDeep*/, bool /*aNullParent*/)
|
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
|
2012-03-28 08:53:56 -07:00
|
|
|
MOZ_ASSERT(thisContent);
|
|
|
|
nsIDocument* ownerDoc = thisContent->OwnerDoc();
|
|
|
|
ownerDoc->RemovePlugin(this);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsObjectLoadingContent::nsObjectLoadingContent()
|
2007-07-05 15:44:27 -07:00
|
|
|
: mPendingInstantiateEvent(nsnull)
|
|
|
|
, mChannel(nsnull)
|
2007-03-22 10:30:00 -07:00
|
|
|
, mType(eType_Loading)
|
2011-10-17 07:59:28 -07:00
|
|
|
, mInstantiating(false)
|
2012-07-25 13:39:01 -07:00
|
|
|
, mUserDisabled(false)
|
|
|
|
, mSuppressed(false)
|
2011-10-17 07:59:28 -07:00
|
|
|
, mNetworkCreated(true)
|
2012-05-25 15:34:11 -07:00
|
|
|
, mIsStopping(false)
|
2012-07-25 13:39:01 -07:00
|
|
|
, mSrcStreamLoading(false)
|
|
|
|
, mFallbackReason(ePluginOtherState)
|
|
|
|
, mCTPPlayable(false)
|
|
|
|
, mActivated(false) {}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsObjectLoadingContent::~nsObjectLoadingContent()
|
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
DestroyImageLoadingContent();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mFrameLoader) {
|
|
|
|
mFrameLoader->Destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
nsresult
|
2012-07-25 13:39:01 -07:00
|
|
|
nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI)
|
2012-01-31 13:55:54 -08:00
|
|
|
{
|
|
|
|
// Don't do anything if we already have an active instance.
|
|
|
|
if (mInstanceOwner) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't allow re-entry into initialization code.
|
|
|
|
if (mInstantiating) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
mInstantiating = true;
|
|
|
|
AutoSetInstantiatingToFalse autoInstantiating(this);
|
|
|
|
|
|
|
|
// Instantiating an instance can result in script execution, which
|
|
|
|
// can destroy this DOM object. Don't allow that for the scope
|
|
|
|
// of this method.
|
|
|
|
nsCOMPtr<nsIObjectLoadingContent> kungFuDeathGrip = this;
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
|
|
|
if (!aURI) {
|
|
|
|
// We need some URI. If we have nothing else, use the base URI.
|
|
|
|
// XXX(biesi): The code used to do this. Not sure why this is correct...
|
|
|
|
GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
|
|
|
|
aURI = baseURI;
|
|
|
|
}
|
2012-01-31 13:55:54 -08:00
|
|
|
|
|
|
|
// Flush layout so that the plugin is initialized with the latest information.
|
|
|
|
nsIDocument* doc = thisContent->GetCurrentDoc();
|
|
|
|
if (!doc) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2012-05-29 06:13:36 -07:00
|
|
|
if (!doc->IsActive()) {
|
2012-07-25 13:39:01 -07:00
|
|
|
NS_ERROR("Shouldn't be calling InstantiatePluginInstance in an inactive document");
|
2012-05-29 06:13:36 -07:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2012-01-31 13:55:54 -08:00
|
|
|
doc->FlushPendingNotifications(Flush_Layout);
|
|
|
|
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv));
|
|
|
|
nsPluginHost* pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!pluginHost->IsPluginClickToPlayForType(aMimeType)) {
|
|
|
|
mCTPPlayable = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mCTPPlayable) {
|
|
|
|
return NS_ERROR_PLUGIN_CLICKTOPLAY;
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If you add early return(s), be sure to balance this call to
|
|
|
|
// appShell->SuspendNative() with additional call(s) to
|
|
|
|
// appShell->ReturnNative().
|
|
|
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
|
|
|
if (appShell) {
|
|
|
|
appShell->SuspendNative();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(doc));
|
|
|
|
bool fullPageMode = false;
|
|
|
|
if (pDoc) {
|
|
|
|
pDoc->GetWillHandleInstantiation(&fullPageMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fullPageMode) {
|
|
|
|
nsCOMPtr<nsIStreamListener> stream;
|
2012-07-25 13:39:01 -07:00
|
|
|
rv = pluginHost->InstantiateFullPagePluginInstance(aMimeType, aURI, this,
|
|
|
|
getter_AddRefs(mInstanceOwner), getter_AddRefs(stream));
|
2012-01-31 13:55:54 -08:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
pDoc->SetStreamListener(stream);
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-25 13:39:01 -07:00
|
|
|
rv = pluginHost->InstantiateEmbeddedPluginInstance(aMimeType, aURI, this,
|
2012-04-15 14:34:01 -07:00
|
|
|
getter_AddRefs(mInstanceOwner));
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (appShell) {
|
|
|
|
appShell->ResumeNative();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up scripting interfaces.
|
|
|
|
NotifyContentObjectWrapper();
|
|
|
|
|
|
|
|
nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
|
|
|
|
GetPluginInstance(getter_AddRefs(pluginInstance));
|
|
|
|
if (pluginInstance) {
|
|
|
|
nsCOMPtr<nsIPluginTag> pluginTag;
|
2012-07-25 13:39:01 -07:00
|
|
|
pluginHost->GetPluginTagForInstance(pluginInstance, getter_AddRefs(pluginTag));
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
nsCOMPtr<nsIBlocklistService> blocklist =
|
2012-07-25 13:39:01 -07:00
|
|
|
do_GetService("@mozilla.org/extensions/blocklist;1");
|
2012-01-31 13:55:54 -08:00
|
|
|
if (blocklist) {
|
|
|
|
PRUint32 blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
|
|
|
|
blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
|
|
|
|
EmptyString(), &blockState);
|
|
|
|
if (blockState == nsIBlocklistService::STATE_OUTDATED)
|
2012-07-25 13:39:01 -07:00
|
|
|
FirePluginError(thisContent, ePluginOutdated);
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
mActivated = true;
|
2012-01-31 13:55:54 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged()
|
|
|
|
{
|
|
|
|
if (!mInstanceOwner) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
2012-01-31 13:55:54 -08:00
|
|
|
nsIDocument* ownerDoc = thisContent->OwnerDoc();
|
|
|
|
if (!ownerDoc->IsActive()) {
|
|
|
|
StopPluginInstance();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// nsIRequestObserver
|
|
|
|
NS_IMETHODIMP
|
2008-03-27 16:12:18 -07:00
|
|
|
nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
|
|
|
|
nsISupports *aContext)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-01-18 16:53:35 -08:00
|
|
|
SAMPLE_LABEL("nsObjectLoadingContent", "OnStartRequest");
|
2012-01-31 13:55:54 -08:00
|
|
|
|
2011-11-03 22:23:26 -07:00
|
|
|
if (aRequest != mChannel || !aRequest) {
|
2012-07-25 13:39:01 -07:00
|
|
|
// This is a bit of an edge case - happens when a new load starts before the
|
|
|
|
// previous one got here
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
AutoNotifier notifier(this, true);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!IsSuccessfulRequest(aRequest)) {
|
|
|
|
LOG(("OBJLC [%p]: OnStartRequest: Request failed\n", this));
|
|
|
|
Fallback(false);
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
|
|
|
|
NS_ASSERTION(chan, "Why is our request not a channel?");
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsresult rv = NS_ERROR_UNEXPECTED;
|
|
|
|
// This fallback variable MUST be declared after the notifier variable. Do NOT
|
|
|
|
// change the order of the declarations!
|
|
|
|
AutoFallback fallback(this, &rv);
|
|
|
|
|
|
|
|
nsCString channelType;
|
|
|
|
rv = chan->GetContentType(channelType);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (channelType.EqualsASCII(APPLICATION_GUESS_FROM_EXT)) {
|
|
|
|
channelType = APPLICATION_OCTET_STREAM;
|
|
|
|
chan->SetContentType(channelType);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// We want to ignore the channel type if one of the following is true:
|
|
|
|
//
|
|
|
|
// 1) The channel type is application/octet-stream or binary/octet-stream
|
|
|
|
// and we have a type hint (in mContentType) and the type hint is not a
|
|
|
|
// document type.
|
|
|
|
// 2) Our type hint is a type that we support with a plugin
|
|
|
|
// (where "support" means it is enabled or it is click-to-play)
|
|
|
|
// and this object loading content has the capability to load a plugin.
|
|
|
|
// We have to be careful here - there might be a plugin that supports
|
|
|
|
// image types, so make sure the type of the content is not an image.
|
|
|
|
bool isOctetStream = (channelType.EqualsASCII(APPLICATION_OCTET_STREAM) ||
|
|
|
|
channelType.EqualsASCII(BINARY_OCTET_STREAM));
|
|
|
|
ObjectType typeOfContent = GetTypeOfContent(mContentType);
|
|
|
|
bool caseOne = (isOctetStream &&
|
|
|
|
!mContentType.IsEmpty() &&
|
|
|
|
typeOfContent != eType_Document);
|
|
|
|
nsresult pluginState = IsPluginEnabledForType(mContentType);
|
|
|
|
bool pluginSupported = (NS_SUCCEEDED(pluginState) ||
|
|
|
|
pluginState == NS_ERROR_PLUGIN_CLICKTOPLAY);
|
|
|
|
PRUint32 caps = GetCapabilities();
|
|
|
|
bool caseTwo = (pluginSupported &&
|
|
|
|
(caps & eSupportPlugins) &&
|
|
|
|
typeOfContent != eType_Image &&
|
|
|
|
typeOfContent != eType_Document);
|
|
|
|
if (caseOne || caseTwo) {
|
|
|
|
// Set the type we'll use for dispatch on the channel. Otherwise we could
|
|
|
|
// end up trying to dispatch to a nsFrameLoader, which will complain that
|
|
|
|
// it couldn't find a way to handle application/octet-stream
|
|
|
|
nsCAutoString typeHint, dummy;
|
|
|
|
NS_ParseContentType(mContentType, typeHint, dummy);
|
|
|
|
if (!typeHint.IsEmpty()) {
|
|
|
|
chan->SetContentType(typeHint);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mContentType = channelType;
|
2007-08-20 20:26:12 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
chan->GetURI(getter_AddRefs(uri));
|
2012-04-24 13:25:21 -07:00
|
|
|
if (!uri) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2008-03-27 16:12:18 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (mContentType.EqualsASCII(APPLICATION_OCTET_STREAM) ||
|
|
|
|
mContentType.EqualsASCII(BINARY_OCTET_STREAM)) {
|
|
|
|
nsCAutoString extType;
|
|
|
|
if (IsPluginEnabledByExtension(uri, extType)) {
|
|
|
|
mContentType = extType;
|
|
|
|
chan->SetContentType(extType);
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Now find out what type the content is
|
|
|
|
// UnloadContent will set our type to null; need to be sure to only set it to
|
|
|
|
// the real value on success
|
|
|
|
ObjectType newType = GetTypeOfContent(mContentType);
|
|
|
|
LOG(("OBJLC [%p]: OnStartRequest: Content Type=<%s> Old type=%u New Type=%u\n",
|
|
|
|
this, mContentType.get(), mType, newType));
|
2011-11-03 22:23:26 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Now do a content policy check
|
|
|
|
// XXXbz this duplicates some code in nsContentBlocker::ShouldLoad
|
|
|
|
PRInt32 contentPolicyType;
|
|
|
|
switch (newType) {
|
|
|
|
case eType_Image:
|
|
|
|
contentPolicyType = nsIContentPolicy::TYPE_IMAGE;
|
|
|
|
break;
|
|
|
|
case eType_Document:
|
|
|
|
contentPolicyType = nsIContentPolicy::TYPE_SUBDOCUMENT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
contentPolicyType = nsIContentPolicy::TYPE_OBJECT;
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> thisContent =
|
|
|
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
NS_ASSERTION(thisContent, "must be a content");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsIDocument* doc = thisContent->OwnerDoc();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
PRInt16 shouldProcess = nsIContentPolicy::ACCEPT;
|
|
|
|
rv =
|
|
|
|
NS_CheckContentProcessPolicy(contentPolicyType,
|
|
|
|
uri,
|
|
|
|
doc->NodePrincipal(),
|
|
|
|
static_cast<nsIImageLoadingContent*>(this),
|
|
|
|
mContentType,
|
|
|
|
nsnull, //extra
|
|
|
|
&shouldProcess,
|
|
|
|
nsContentUtils::GetContentPolicy(),
|
|
|
|
nsContentUtils::GetSecurityManager());
|
|
|
|
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldProcess)) {
|
|
|
|
HandleBeingBlockedByContentPolicy(rv, shouldProcess);
|
|
|
|
rv = NS_OK; // otherwise, the AutoFallback will make us fall back
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mType != newType) {
|
|
|
|
UnloadContent();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (newType) {
|
|
|
|
case eType_Image:
|
|
|
|
rv = LoadImageWithChannel(chan, getter_AddRefs(mFinalListener));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// If we have a success result but no final listener, then the image is
|
|
|
|
// cached. In that case, we can just return: No need to try to call the
|
|
|
|
// final listener.
|
|
|
|
if (!mFinalListener) {
|
|
|
|
mType = newType;
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case eType_Document: {
|
|
|
|
if (!mFrameLoader) {
|
|
|
|
mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
|
|
|
|
mNetworkCreated);
|
|
|
|
if (!mFrameLoader) {
|
|
|
|
Fallback(false);
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = mFrameLoader->CheckForRecursiveLoad(uri);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
Fallback(false);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mType != newType) {
|
|
|
|
// XXX We must call this before getting the docshell to work around
|
|
|
|
// bug 300540; when that's fixed, this if statement can be removed.
|
|
|
|
mType = newType;
|
|
|
|
notifier.Notify();
|
|
|
|
|
|
|
|
if (!mFrameLoader) {
|
|
|
|
// mFrameLoader got nulled out when we notified, which most
|
|
|
|
// likely means the node was removed from the
|
|
|
|
// document. Abort the load that just started.
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're loading a document, so we have to set LOAD_DOCUMENT_URI
|
|
|
|
// (especially important for firing onload)
|
|
|
|
nsLoadFlags flags = 0;
|
|
|
|
chan->GetLoadFlags(&flags);
|
|
|
|
flags |= nsIChannel::LOAD_DOCUMENT_URI;
|
|
|
|
chan->SetLoadFlags(flags);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell;
|
|
|
|
rv = mFrameLoader->GetDocShell(getter_AddRefs(docShell));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(docShell));
|
|
|
|
NS_ASSERTION(req, "Docshell must be an ifreq");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURILoader>
|
|
|
|
uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID, &rv));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = uriLoader->OpenChannel(chan, nsIURILoader::DONT_RETARGET, req,
|
|
|
|
getter_AddRefs(mFinalListener));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case eType_Plugin: {
|
|
|
|
if (mType != newType) {
|
|
|
|
mType = newType;
|
|
|
|
notifier.Notify();
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
|
|
|
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
|
|
|
if (!pluginHost) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
pluginHost->NewEmbeddedPluginStreamListener(uri, this, nsnull,
|
|
|
|
getter_AddRefs(mFinalListener));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case eType_Loading:
|
|
|
|
NS_NOTREACHED("Should not have a loading type here!");
|
|
|
|
case eType_Null:
|
|
|
|
// Need to fallback here (instead of using the case below), so that we can
|
|
|
|
// set mFallbackReason without it being overwritten. This is also why we
|
|
|
|
// return early.
|
|
|
|
Fallback(false);
|
|
|
|
|
|
|
|
PluginSupportState pluginState = GetPluginSupportState(thisContent,
|
|
|
|
mContentType);
|
|
|
|
// Do nothing, but fire the plugin not found event if needed
|
|
|
|
if (pluginState != ePluginOtherState) {
|
|
|
|
mFallbackReason = pluginState;
|
|
|
|
FirePluginError(thisContent, pluginState);
|
|
|
|
}
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mFinalListener) {
|
|
|
|
mType = newType;
|
|
|
|
|
|
|
|
mSrcStreamLoading = true;
|
|
|
|
rv = mFinalListener->OnStartRequest(aRequest, aContext);
|
|
|
|
mSrcStreamLoading = false;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// Plugins need to set up for NPRuntime.
|
|
|
|
if (mType == eType_Plugin) {
|
|
|
|
NotifyContentObjectWrapper();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Plugins don't fall back if there is an error here.
|
|
|
|
if (mType == eType_Plugin) {
|
|
|
|
rv = NS_OK; // this is necessary to avoid auto-fallback
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
Fallback(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
Fallback(false);
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::OnStopRequest(nsIRequest *aRequest,
|
|
|
|
nsISupports *aContext,
|
|
|
|
nsresult aStatusCode)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
|
|
|
|
|
|
|
if (aRequest != mChannel) {
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
mChannel = nsnull;
|
|
|
|
|
|
|
|
if (mFinalListener) {
|
|
|
|
mFinalListener->OnStopRequest(aRequest, aContext, aStatusCode);
|
2007-03-22 10:30:00 -07:00
|
|
|
mFinalListener = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return value doesn't matter
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// nsIStreamListener
|
|
|
|
NS_IMETHODIMP
|
2011-11-03 22:23:26 -07:00
|
|
|
nsObjectLoadingContent::OnDataAvailable(nsIRequest *aRequest,
|
|
|
|
nsISupports *aContext,
|
|
|
|
nsIInputStream *aInputStream,
|
|
|
|
PRUint32 aOffset, PRUint32 aCount)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-11-03 22:23:26 -07:00
|
|
|
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aRequest != mChannel) {
|
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mFinalListener) {
|
2012-07-25 13:39:01 -07:00
|
|
|
return mFinalListener->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Abort this load if we have no listener here
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsIFrameLoaderOwner
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::GetFrameLoader(nsIFrameLoader** aFrameLoader)
|
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
*aFrameLoader = mFrameLoader;
|
|
|
|
NS_IF_ADDREF(*aFrameLoader);
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-20 14:33:59 -07:00
|
|
|
NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
|
|
|
|
nsObjectLoadingContent::GetFrameLoader()
|
|
|
|
{
|
|
|
|
nsFrameLoader* loader = mFrameLoader;
|
|
|
|
NS_IF_ADDREF(loader);
|
|
|
|
return loader;
|
|
|
|
}
|
|
|
|
|
2008-08-11 01:38:43 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// nsIObjectLoadingContent
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::GetActualType(nsACString& aType)
|
|
|
|
{
|
|
|
|
aType = mContentType;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::GetDisplayedType(PRUint32* aType)
|
|
|
|
{
|
|
|
|
*aType = mType;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-01-31 13:55:54 -08:00
|
|
|
nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
// Not having an instance yet is OK, but try to start one now that
|
|
|
|
// we have a frame.
|
|
|
|
if (!mInstanceOwner) {
|
|
|
|
AsyncStartPluginInstance();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-08-29 23:09:56 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Disconnect any existing frame
|
|
|
|
DisconnectFrame();
|
2011-08-29 23:09:56 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Set up relationship between instance owner and frame.
|
|
|
|
nsObjectFrame *objFrame = static_cast<nsObjectFrame*>(aFrame);
|
|
|
|
mInstanceOwner->SetFrame(objFrame);
|
|
|
|
|
|
|
|
// Set up new frame to draw.
|
|
|
|
objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size());
|
|
|
|
objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf());
|
2011-08-29 23:09:56 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-01-31 13:55:54 -08:00
|
|
|
nsObjectLoadingContent::DisconnectFrame()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-01-31 13:55:54 -08:00
|
|
|
if (mInstanceOwner) {
|
|
|
|
mInstanceOwner->SetFrame(nsnull);
|
2011-08-29 23:09:56 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-03-14 16:08:57 -07:00
|
|
|
NS_IMETHODIMP
|
2011-05-17 18:48:34 -07:00
|
|
|
nsObjectLoadingContent::GetPluginInstance(nsNPAPIPluginInstance** aInstance)
|
2008-03-14 16:08:57 -07:00
|
|
|
{
|
|
|
|
*aInstance = nsnull;
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
if (!mInstanceOwner) {
|
2008-03-14 16:08:57 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
return mInstanceOwner->GetInstance(aInstance);
|
2008-03-14 16:08:57 -07:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::GetContentTypeForMIMEType(const nsACString& aMIMEType,
|
|
|
|
PRUint32* aType)
|
|
|
|
{
|
|
|
|
*aType = GetTypeOfContent(PromiseFlatCString(aMIMEType));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsIInterfaceRequestor
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::GetInterface(const nsIID & aIID, void **aResult)
|
|
|
|
{
|
|
|
|
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
|
|
|
|
nsIChannelEventSink* sink = this;
|
|
|
|
*aResult = sink;
|
|
|
|
NS_ADDREF(sink);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsIChannelEventSink
|
|
|
|
NS_IMETHODIMP
|
2010-08-04 19:15:55 -07:00
|
|
|
nsObjectLoadingContent::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
|
|
|
nsIChannel *aNewChannel,
|
|
|
|
PRUint32 aFlags,
|
|
|
|
nsIAsyncVerifyRedirectCallback *cb)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-02-28 11:26:05 -08:00
|
|
|
// If we're already busy with a new load, or have no load at all,
|
|
|
|
// cancel the redirect.
|
|
|
|
if (!mChannel || aOldChannel != mChannel) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_BINDING_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
mChannel = aNewChannel;
|
2010-08-04 19:15:55 -07:00
|
|
|
cb->OnRedirectVerifyCallback(NS_OK);
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// <public>
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates
|
2007-03-22 10:30:00 -07:00
|
|
|
nsObjectLoadingContent::ObjectState() const
|
|
|
|
{
|
|
|
|
switch (mType) {
|
|
|
|
case eType_Loading:
|
|
|
|
return NS_EVENT_STATE_LOADING;
|
|
|
|
case eType_Image:
|
|
|
|
return ImageState();
|
|
|
|
case eType_Plugin:
|
2011-11-19 20:08:27 -08:00
|
|
|
case eType_Document:
|
2007-03-22 10:30:00 -07:00
|
|
|
// These are OK. If documents start to load successfully, they display
|
|
|
|
// something, and are thus not broken in this sense. The same goes for
|
|
|
|
// plugins.
|
2010-10-20 04:26:32 -07:00
|
|
|
return nsEventStates();
|
2007-03-22 10:30:00 -07:00
|
|
|
case eType_Null:
|
2012-07-25 13:39:01 -07:00
|
|
|
if (mSuppressed)
|
|
|
|
return NS_EVENT_STATE_SUPPRESSED;
|
|
|
|
if (mUserDisabled)
|
|
|
|
return NS_EVENT_STATE_USERDISABLED;
|
|
|
|
|
|
|
|
// Otherwise, broken
|
|
|
|
nsEventStates state = NS_EVENT_STATE_BROKEN;
|
|
|
|
switch (mFallbackReason) {
|
|
|
|
case ePluginClickToPlay:
|
2011-10-07 10:46:02 -07:00
|
|
|
return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginVulnerableUpdatable:
|
2012-07-11 08:56:34 -07:00
|
|
|
return NS_EVENT_STATE_VULNERABLE_UPDATABLE;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginVulnerableNoUpdate:
|
2012-07-11 08:56:34 -07:00
|
|
|
return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
|
2012-07-25 13:39:01 -07:00
|
|
|
case ePluginDisabled:
|
|
|
|
state |= NS_EVENT_STATE_HANDLER_DISABLED;
|
|
|
|
break;
|
|
|
|
case ePluginBlocklisted:
|
|
|
|
state |= NS_EVENT_STATE_HANDLER_BLOCKED;
|
|
|
|
break;
|
|
|
|
case ePluginCrashed:
|
|
|
|
state |= NS_EVENT_STATE_HANDLER_CRASHED;
|
|
|
|
break;
|
|
|
|
case ePluginUnsupported:
|
|
|
|
state |= NS_EVENT_STATE_TYPE_UNSUPPORTED;
|
|
|
|
break;
|
|
|
|
case ePluginOutdated:
|
|
|
|
case ePluginOtherState:
|
|
|
|
// Do nothing, but avoid a compile warning
|
|
|
|
break;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
return state;
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
NS_NOTREACHED("unknown type?");
|
2012-07-25 13:39:01 -07:00
|
|
|
// this return statement only exists to avoid a compile warning
|
|
|
|
return nsEventStates();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// <protected>
|
|
|
|
nsresult
|
|
|
|
nsObjectLoadingContent::LoadObject(const nsAString& aURI,
|
|
|
|
bool aNotify,
|
|
|
|
const nsCString& aTypeHint,
|
|
|
|
bool aForceLoad)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
LOG(("OBJLC [%p]: Loading object: URI string=<%s> notify=%i type=<%s> forceload=%i\n",
|
|
|
|
this, NS_ConvertUTF16toUTF8(aURI).get(), aNotify, aTypeHint.get(), aForceLoad));
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Avoid StringToURI in order to use the codebase attribute as base URI
|
|
|
|
nsCOMPtr<nsIContent> thisContent =
|
|
|
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
NS_ASSERTION(thisContent, "must be a content");
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsIDocument* doc = thisContent->OwnerDoc();
|
|
|
|
nsCOMPtr<nsIURI> baseURI;
|
|
|
|
GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri),
|
|
|
|
aURI, doc,
|
|
|
|
baseURI);
|
|
|
|
// If URI creation failed, fallback immediately - this only happens for
|
|
|
|
// malformed URIs
|
|
|
|
if (!uri) {
|
|
|
|
Fallback(aNotify);
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
NS_TryToSetImmutable(uri);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
return LoadObject(uri, aNotify, aTypeHint, aForceLoad);
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
void
|
|
|
|
nsObjectLoadingContent::UpdateFallbackState(nsIContent* aContent,
|
|
|
|
AutoFallback& fallback,
|
|
|
|
const nsCString& aTypeHint)
|
2012-07-05 14:07:46 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
// Notify the UI and update the fallback state
|
|
|
|
PluginSupportState state = GetPluginSupportState(aContent, aTypeHint);
|
|
|
|
if (state != ePluginOtherState) {
|
|
|
|
fallback.SetPluginState(state);
|
|
|
|
FirePluginError(aContent, state);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsresult
|
|
|
|
nsObjectLoadingContent::LoadObject(nsIURI* aURI,
|
|
|
|
bool aNotify,
|
|
|
|
const nsCString& aTypeHint,
|
|
|
|
bool aForceLoad)
|
2012-07-05 14:07:46 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
// Only do a URI equality check for things that aren't stopped plugins.
|
|
|
|
// This is because we still need to load again if the plugin has been stopped.
|
|
|
|
if (mType == eType_Document || mType == eType_Image || mInstanceOwner) {
|
|
|
|
if (mURI && aURI) {
|
|
|
|
bool equal;
|
|
|
|
nsresult rv = mURI->Equals(aURI, &equal);
|
|
|
|
if (NS_SUCCEEDED(rv) && equal && !aForceLoad) {
|
|
|
|
// URI didn't change, do nothing
|
|
|
|
return NS_OK;
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
StopPluginInstance();
|
2009-12-10 20:02:13 -08:00
|
|
|
}
|
2007-07-26 19:49:18 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Need to revoke any potentially pending instantiate events
|
|
|
|
if (mType == eType_Plugin && mPendingInstantiateEvent) {
|
|
|
|
mPendingInstantiateEvent = nsnull;
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
AutoNotifier notifier(this, aNotify);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
mUserDisabled = mSuppressed = false;
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
mURI = aURI;
|
|
|
|
mContentType = aTypeHint;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> thisContent =
|
2012-07-05 14:07:46 -07:00
|
|
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
NS_ASSERTION(thisContent, "must be a content");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsIDocument* doc = thisContent->OwnerDoc();
|
|
|
|
if (doc->IsBeingUsedAsImage()) {
|
2012-07-05 14:07:46 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// From here on, we will always change the content. This means that a
|
|
|
|
// possibly-loading channel should be aborted.
|
|
|
|
if (mChannel) {
|
|
|
|
LOG(("OBJLC [%p]: Cancelling existing load\n", this));
|
2012-07-05 13:47:39 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// These three statements are carefully ordered:
|
|
|
|
// - onStopRequest should get a channel whose status is the same as the
|
|
|
|
// status argument
|
|
|
|
// - onStopRequest must get a non-null channel
|
|
|
|
mChannel->Cancel(NS_BINDING_ABORTED);
|
|
|
|
if (mFinalListener) {
|
|
|
|
// NOTE: Since mFinalListener is only set in onStartRequest, which takes
|
|
|
|
// care of calling mFinalListener->OnStartRequest, mFinalListener is only
|
|
|
|
// non-null here if onStartRequest was already called.
|
|
|
|
mFinalListener->OnStopRequest(mChannel, nsnull, NS_BINDING_ABORTED);
|
|
|
|
mFinalListener = nsnull;
|
2012-07-05 13:47:39 -07:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
mChannel = nsnull;
|
2012-07-05 13:47:39 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Security checks
|
|
|
|
if (doc->IsLoadedAsData()) {
|
|
|
|
if (!doc->IsStaticDocument()) {
|
|
|
|
Fallback(false);
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Can't do security checks without a URI - hopefully the plugin will take
|
|
|
|
// care of that
|
|
|
|
// Null URIs happen when the URL to load is specified via other means than the
|
|
|
|
// data/src attribute, for example via custom <param> elements.
|
|
|
|
if (aURI) {
|
|
|
|
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
|
|
|
NS_ASSERTION(secMan, "No security manager!?");
|
|
|
|
nsresult rv =
|
|
|
|
secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), aURI, 0);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
Fallback(false);
|
|
|
|
return NS_OK;
|
2012-07-05 13:47:39 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; // default permit
|
|
|
|
rv =
|
|
|
|
NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OBJECT,
|
|
|
|
aURI,
|
|
|
|
doc->NodePrincipal(),
|
|
|
|
static_cast<nsIImageLoadingContent*>(this),
|
|
|
|
aTypeHint,
|
|
|
|
nsnull, //extra
|
|
|
|
&shouldLoad,
|
|
|
|
nsContentUtils::GetContentPolicy(),
|
|
|
|
secMan);
|
|
|
|
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
|
|
|
HandleBeingBlockedByContentPolicy(rv, shouldLoad);
|
|
|
|
return NS_OK;
|
2012-07-05 13:47:39 -07:00
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsresult rv = NS_ERROR_UNEXPECTED;
|
|
|
|
// This fallback variable MUST be declared after the notifier variable. Do NOT
|
|
|
|
// change the order of the declarations!
|
|
|
|
AutoFallback fallback(this, &rv);
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
PRUint32 caps = GetCapabilities();
|
|
|
|
LOG(("OBJLC [%p]: Capabilities: %04x\n", this, caps));
|
|
|
|
|
|
|
|
nsCAutoString overrideType;
|
|
|
|
if ((caps & eOverrideServerType) &&
|
|
|
|
((!aTypeHint.IsEmpty() && NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) ||
|
|
|
|
(aURI && IsPluginEnabledByExtension(aURI, overrideType)))) {
|
|
|
|
ObjectType newType;
|
|
|
|
if (overrideType.IsEmpty()) {
|
|
|
|
newType = GetTypeOfContent(aTypeHint);
|
|
|
|
} else {
|
|
|
|
mContentType = overrideType;
|
|
|
|
newType = eType_Plugin;
|
|
|
|
}
|
2012-07-05 13:47:39 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (newType != mType) {
|
|
|
|
LOG(("OBJLC [%p]: (eOverrideServerType) Changing type from %u to %u\n", this, mType, newType));
|
2012-07-05 13:47:39 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
UnloadContent();
|
2012-07-05 13:47:39 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Must have a frameloader before creating a frame, or the frame will
|
|
|
|
// create its own.
|
|
|
|
if (!mFrameLoader && newType == eType_Document) {
|
2012-07-05 14:07:46 -07:00
|
|
|
mFrameLoader = nsFrameLoader::Create(thisContent->AsElement(),
|
|
|
|
mNetworkCreated);
|
|
|
|
if (!mFrameLoader) {
|
2012-07-25 13:39:01 -07:00
|
|
|
mURI = nsnull;
|
|
|
|
return NS_OK;
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// Must notify here for plugins
|
|
|
|
// If aNotify is false, we'll just wait until we get a frame and use the
|
|
|
|
// async instantiate path.
|
|
|
|
// XXX is this still needed? (for documents?)
|
|
|
|
mType = newType;
|
|
|
|
if (aNotify)
|
|
|
|
notifier.Notify();
|
|
|
|
}
|
|
|
|
switch (newType) {
|
|
|
|
case eType_Image:
|
|
|
|
// Don't notify, because we will take care of that ourselves.
|
|
|
|
if (aURI) {
|
|
|
|
rv = LoadImage(aURI, aForceLoad, false);
|
|
|
|
} else {
|
|
|
|
rv = NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2012-07-05 13:47:39 -07:00
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case eType_Plugin:
|
|
|
|
rv = AsyncStartPluginInstance();
|
2012-07-05 13:47:39 -07:00
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case eType_Document:
|
|
|
|
if (aURI) {
|
|
|
|
rv = mFrameLoader->LoadURI(aURI);
|
|
|
|
} else {
|
|
|
|
rv = NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2012-07-05 13:47:39 -07:00
|
|
|
break;
|
2012-07-25 13:39:01 -07:00
|
|
|
case eType_Loading:
|
|
|
|
NS_NOTREACHED("Should not have a loading type here!");
|
|
|
|
case eType_Null:
|
|
|
|
// No need to load anything, notify of the failure.
|
|
|
|
UpdateFallbackState(thisContent, fallback, aTypeHint);
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
return NS_OK;
|
2012-07-05 13:47:39 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// If the class ID specifies a supported plugin, or if we have no explicit URI
|
|
|
|
// but a type, immediately instantiate the plugin.
|
|
|
|
bool isSupportedClassID = false;
|
|
|
|
nsCAutoString typeForID; // Will be set iff isSupportedClassID == true
|
|
|
|
bool hasID = false;
|
|
|
|
if (caps & eSupportClassID) {
|
|
|
|
nsAutoString classid;
|
|
|
|
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::classid, classid);
|
|
|
|
if (!classid.IsEmpty()) {
|
|
|
|
hasID = true;
|
|
|
|
isSupportedClassID = NS_SUCCEEDED(TypeForClassID(classid, typeForID));
|
2012-07-05 13:47:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (hasID && !isSupportedClassID) {
|
|
|
|
// We have a class ID and it's unsupported. Fallback in that case.
|
|
|
|
rv = NS_ERROR_NOT_AVAILABLE;
|
|
|
|
return NS_OK;
|
2012-07-05 13:47:39 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (isSupportedClassID ||
|
|
|
|
(!aURI && !aTypeHint.IsEmpty() &&
|
|
|
|
GetTypeOfContent(aTypeHint) == eType_Plugin)) {
|
|
|
|
// No URI, but we have a type. The plugin will handle the load.
|
|
|
|
// Or: supported class id, plugin will handle the load.
|
|
|
|
mType = eType_Plugin;
|
|
|
|
|
|
|
|
// At this point, the stored content type
|
|
|
|
// must be equal to our type hint. Similar,
|
|
|
|
// our URI must be the requested URI.
|
|
|
|
// (->Equals would suffice, but == is cheaper
|
|
|
|
// and handles NULL)
|
|
|
|
NS_ASSERTION(mContentType.Equals(aTypeHint), "mContentType wrong!");
|
|
|
|
NS_ASSERTION(mURI == aURI, "mURI wrong!");
|
|
|
|
|
|
|
|
if (isSupportedClassID) {
|
|
|
|
// Use the classid's type
|
|
|
|
NS_ASSERTION(!typeForID.IsEmpty(), "Must have a real type!");
|
|
|
|
mContentType = typeForID;
|
|
|
|
// XXX(biesi). The plugin instantiation code used to pass the base URI
|
|
|
|
// here instead of the plugin URI for instantiation via class ID, so I
|
|
|
|
// continue to do so. Why that is, no idea...
|
|
|
|
GetObjectBaseURI(thisContent, getter_AddRefs(mURI));
|
|
|
|
if (!mURI) {
|
|
|
|
mURI = aURI;
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
|
|
|
|
// rv is references by a stack-based object, need to assign here
|
|
|
|
rv = AsyncStartPluginInstance();
|
|
|
|
|
|
|
|
return rv;
|
2012-07-05 14:07:46 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!aURI) {
|
|
|
|
// No URI and if we have got this far no enabled plugin supports the type
|
|
|
|
rv = NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
|
|
// We should only notify the UI if there is at least a type to go on for
|
|
|
|
// finding a plugin to use, unless it's a supported image or document type.
|
|
|
|
if (!aTypeHint.IsEmpty() && GetTypeOfContent(aTypeHint) == eType_Null) {
|
|
|
|
UpdateFallbackState(thisContent, fallback, aTypeHint);
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-07-05 14:07:46 -07:00
|
|
|
|
|
|
|
// E.g. mms://
|
2012-07-25 13:39:01 -07:00
|
|
|
if (!CanHandleURI(aURI)) {
|
|
|
|
if (aTypeHint.IsEmpty()) {
|
|
|
|
rv = NS_ERROR_NOT_AVAILABLE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(IsPluginEnabledForType(aTypeHint))) {
|
|
|
|
mType = eType_Plugin;
|
|
|
|
} else {
|
|
|
|
rv = NS_ERROR_NOT_AVAILABLE;
|
|
|
|
// No plugin to load, notify of the failure.
|
|
|
|
UpdateFallbackState(thisContent, fallback, aTypeHint);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsILoadGroup> group = doc->GetDocumentLoadGroup();
|
|
|
|
nsCOMPtr<nsIChannel> chan;
|
2010-04-23 12:51:25 -07:00
|
|
|
nsCOMPtr<nsIChannelPolicy> channelPolicy;
|
|
|
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
|
|
|
rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (csp) {
|
|
|
|
channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
|
|
|
|
channelPolicy->SetContentSecurityPolicy(csp);
|
2012-07-25 13:39:01 -07:00
|
|
|
channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
|
2010-04-23 12:51:25 -07:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
rv = NS_NewChannel(getter_AddRefs(chan), aURI, nsnull, group, this,
|
2010-05-21 14:03:02 -07:00
|
|
|
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
|
|
|
|
nsIChannel::LOAD_CLASSIFY_URI,
|
2010-04-23 12:51:25 -07:00
|
|
|
channelPolicy);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// Referrer
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
|
|
|
|
if (httpChan) {
|
|
|
|
httpChan->SetReferrer(doc->GetDocumentURI());
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// MIME Type hint
|
|
|
|
if (!aTypeHint.IsEmpty()) {
|
|
|
|
nsCAutoString typeHint, dummy;
|
|
|
|
NS_ParseContentType(aTypeHint, typeHint, dummy);
|
|
|
|
if (!typeHint.IsEmpty()) {
|
|
|
|
chan->SetContentType(typeHint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-03 13:57:17 -08:00
|
|
|
// Set up the channel's principal and such, like nsDocShell::DoURILoad does
|
2011-09-20 14:00:42 -07:00
|
|
|
nsContentUtils::SetUpChannelOwner(thisContent->NodePrincipal(),
|
2012-07-25 13:39:01 -07:00
|
|
|
chan, aURI, true);
|
2007-12-03 13:57:17 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(chan);
|
|
|
|
if (scriptChannel) {
|
|
|
|
// Allow execution against our context if the principals match
|
2012-07-25 13:39:01 -07:00
|
|
|
scriptChannel->
|
|
|
|
SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
|
2007-12-03 13:57:17 -08:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// AsyncOpen can fail if a file does not exist.
|
2012-07-25 13:39:01 -07:00
|
|
|
// Show fallback content in that case.
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = chan->AsyncOpen(this, nsnull);
|
2012-07-25 13:39:01 -07:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
LOG(("OBJLC [%p]: Channel opened.\n", this));
|
|
|
|
|
|
|
|
mChannel = chan;
|
|
|
|
mType = eType_Loading;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32
|
|
|
|
nsObjectLoadingContent::GetCapabilities() const
|
|
|
|
{
|
|
|
|
return eSupportImages |
|
|
|
|
eSupportPlugins |
|
2011-05-30 00:34:50 -07:00
|
|
|
eSupportDocuments |
|
|
|
|
eSupportSVG;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-25 13:39:01 -07:00
|
|
|
nsObjectLoadingContent::Fallback(bool aNotify)
|
|
|
|
{
|
|
|
|
AutoNotifier notifier(this, aNotify);
|
|
|
|
|
|
|
|
UnloadContent();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectLoadingContent::RemovedFromDocument()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (mFrameLoader) {
|
2012-07-25 13:39:01 -07:00
|
|
|
// XXX This is very temporary and must go away
|
2007-03-22 10:30:00 -07:00
|
|
|
mFrameLoader->Destroy();
|
|
|
|
mFrameLoader = nsnull;
|
2012-07-25 13:39:01 -07:00
|
|
|
|
|
|
|
// Clear the current URI, so that LoadObject doesn't think that we
|
|
|
|
// have already loaded the content.
|
|
|
|
mURI = nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2012-01-31 13:55:54 -08:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// When a plugin instance node is removed from the document we'll
|
|
|
|
// let the plugin continue to run at least until we get back to
|
|
|
|
// the event loop. If we get back to the event loop and the node
|
|
|
|
// has still not been added back to the document then we stop
|
|
|
|
// the plugin.
|
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
nsCOMPtr<nsIRunnable> event = new InDocCheckEvent(thisContent);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
|
|
|
if (appShell) {
|
|
|
|
appShell->RunInStableState(event);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-08-28 07:07:24 -07:00
|
|
|
/* static */
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
2011-08-28 07:07:24 -07:00
|
|
|
nsObjectLoadingContent::Traverse(nsObjectLoadingContent *tmp,
|
|
|
|
nsCycleCollectionTraversalCallback &cb)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-08-28 07:07:24 -07:00
|
|
|
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameLoader");
|
|
|
|
cb.NoteXPCOMChild(static_cast<nsIFrameLoader*>(tmp->mFrameLoader));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
// <private>
|
|
|
|
/* static */ bool
|
|
|
|
nsObjectLoadingContent::IsSuccessfulRequest(nsIRequest* aRequest)
|
|
|
|
{
|
|
|
|
nsresult status;
|
|
|
|
nsresult rv = aRequest->GetStatus(&status);
|
|
|
|
if (NS_FAILED(rv) || NS_FAILED(status)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This may still be an error page or somesuch
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(aRequest));
|
|
|
|
if (httpChan) {
|
|
|
|
bool success;
|
|
|
|
rv = httpChan->GetRequestSucceeded(&success);
|
|
|
|
if (NS_FAILED(rv) || !success) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, the request is successful
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ bool
|
|
|
|
nsObjectLoadingContent::CanHandleURI(nsIURI* aURI)
|
|
|
|
{
|
|
|
|
nsCAutoString scheme;
|
|
|
|
if (NS_FAILED(aURI->GetScheme(scheme))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIIOService* ios = nsContentUtils::GetIOService();
|
|
|
|
if (!ios)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIProtocolHandler> handler;
|
|
|
|
ios->GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
|
|
|
|
if (!handler) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIExternalProtocolHandler> extHandler =
|
|
|
|
do_QueryInterface(handler);
|
|
|
|
// We can handle this URI if its protocol handler is not the external one
|
|
|
|
return extHandler == nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsObjectLoadingContent::IsSupportedDocument(const nsCString& aMimeType)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> thisContent =
|
|
|
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
NS_ASSERTION(thisContent, "must be a content");
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIWebNavigationInfo> info(
|
|
|
|
do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv));
|
|
|
|
PRUint32 supported;
|
|
|
|
if (info) {
|
|
|
|
nsCOMPtr<nsIWebNavigation> webNav;
|
|
|
|
nsIDocument* currentDoc = thisContent->GetCurrentDoc();
|
|
|
|
if (currentDoc) {
|
|
|
|
webNav = do_GetInterface(currentDoc->GetScriptGlobalObject());
|
|
|
|
}
|
|
|
|
rv = info->IsTypeSupported(aMimeType, webNav, &supported);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (supported == nsIWebNavigationInfo::UNSUPPORTED) {
|
|
|
|
// Try a stream converter
|
|
|
|
// NOTE: We treat any type we can convert from as a supported type. If a
|
|
|
|
// type is not actually supported, the URI loader will detect that and
|
|
|
|
// return an error, and we'll fallback.
|
|
|
|
nsCOMPtr<nsIStreamConverterService> convServ =
|
|
|
|
do_GetService("@mozilla.org/streamConverters;1");
|
|
|
|
bool canConvert = false;
|
|
|
|
if (convServ) {
|
|
|
|
rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_SUCCEEDED(rv) && canConvert;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't want to support plugins as documents
|
|
|
|
return supported != nsIWebNavigationInfo::PLUGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void
|
2012-07-25 13:39:01 -07:00
|
|
|
nsObjectLoadingContent::UnloadContent()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
// Don't notify in CancelImageRequests. We do it ourselves.
|
2011-10-17 07:59:28 -07:00
|
|
|
CancelImageRequests(false);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mFrameLoader) {
|
|
|
|
mFrameLoader->Destroy();
|
|
|
|
mFrameLoader = nsnull;
|
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
mType = eType_Null;
|
|
|
|
mUserDisabled = mSuppressed = false;
|
|
|
|
mFallbackReason = ePluginOtherState;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
|
2011-05-31 18:46:57 -07:00
|
|
|
nsEventStates aOldState,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aSync,
|
|
|
|
bool aNotify)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
LOG(("OBJLC [%p]: Notifying about state change: (%u, %llx) -> (%u, %llx) (sync=%i)\n",
|
|
|
|
this, aOldType, aOldState.GetInternalValue(), mType,
|
|
|
|
ObjectState().GetInternalValue(), aSync));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> thisContent =
|
2007-07-08 00:08:04 -07:00
|
|
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(thisContent, "must be a content");
|
|
|
|
|
2011-05-31 18:46:57 -07:00
|
|
|
NS_ASSERTION(thisContent->IsElement(), "Not an element?");
|
|
|
|
|
|
|
|
// Unfortunately, we do some state changes without notifying
|
|
|
|
// (e.g. in Fallback when canceling image requests), so we have to
|
|
|
|
// manually notify object state changes.
|
|
|
|
thisContent->AsElement()->UpdateState(false);
|
|
|
|
|
|
|
|
if (!aNotify) {
|
|
|
|
// We're done here
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIDocument* doc = thisContent->GetCurrentDoc();
|
|
|
|
if (!doc) {
|
|
|
|
return; // Nothing to do
|
|
|
|
}
|
|
|
|
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates newState = ObjectState();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (newState != aOldState) {
|
|
|
|
// This will trigger frame construction
|
|
|
|
NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
|
2010-10-20 04:26:32 -07:00
|
|
|
nsEventStates changedBits = aOldState ^ newState;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
{
|
2011-05-31 14:38:25 -07:00
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
2011-03-28 20:32:11 -07:00
|
|
|
doc->ContentStateChanged(thisContent, changedBits);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
if (aSync) {
|
2011-05-31 18:46:57 -07:00
|
|
|
// Make sure that frames are actually constructed immediately.
|
2007-03-22 10:30:00 -07:00
|
|
|
doc->FlushPendingNotifications(Flush_Frames);
|
|
|
|
}
|
|
|
|
} else if (aOldType != mType) {
|
|
|
|
// If our state changed, then we already recreated frames
|
|
|
|
// Otherwise, need to do that here
|
2010-06-25 06:59:57 -07:00
|
|
|
nsCOMPtr<nsIPresShell> shell = doc->GetShell();
|
2010-01-07 02:36:11 -08:00
|
|
|
if (shell) {
|
2007-03-22 10:30:00 -07:00
|
|
|
shell->RecreateFramesFor(thisContent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
/* static */ void
|
|
|
|
nsObjectLoadingContent::FirePluginError(nsIContent* thisContent,
|
|
|
|
PluginSupportState state)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
LOG(("OBJLC []: Dispatching nsPluginErrorEvent for content %p\n",
|
|
|
|
thisContent));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIRunnable> ev = new nsPluginErrorEvent(thisContent, state);
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv = NS_DispatchToCurrentThread(ev);
|
|
|
|
if (NS_FAILED(rv)) {
|
2007-07-13 17:28:05 -07:00
|
|
|
NS_WARNING("failed to dispatch nsPluginErrorEvent");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsObjectLoadingContent::ObjectType
|
|
|
|
nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType)
|
|
|
|
{
|
|
|
|
PRUint32 caps = GetCapabilities();
|
|
|
|
|
|
|
|
if ((caps & eSupportImages) && IsSupportedImage(aMIMEType)) {
|
|
|
|
return eType_Image;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool isSVG = aMIMEType.LowerCaseEqualsLiteral("image/svg+xml");
|
2012-07-25 13:39:01 -07:00
|
|
|
bool supportedSVG = isSVG && (caps & eSupportSVG);
|
|
|
|
if (((caps & eSupportDocuments) || supportedSVG) &&
|
|
|
|
IsSupportedDocument(aMIMEType)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return eType_Document;
|
|
|
|
}
|
|
|
|
|
2012-02-10 05:39:40 -08:00
|
|
|
if ((caps & eSupportPlugins) && NS_SUCCEEDED(IsPluginEnabledForType(aMIMEType))) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return eType_Plugin;
|
|
|
|
}
|
|
|
|
|
|
|
|
return eType_Null;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
|
|
|
|
nsACString& aType)
|
|
|
|
{
|
|
|
|
if (StringBeginsWith(aClassID, NS_LITERAL_STRING("java:"))) {
|
|
|
|
// Supported if we have a java plugin
|
|
|
|
aType.AssignLiteral("application/x-java-vm");
|
2012-02-10 05:39:40 -08:00
|
|
|
nsresult rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If it starts with "clsid:", this is ActiveX content
|
2011-02-08 05:35:25 -08:00
|
|
|
if (StringBeginsWith(aClassID, NS_LITERAL_STRING("clsid:"), nsCaseInsensitiveStringComparator())) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// Check if we have a plugin for that
|
|
|
|
|
2012-02-10 05:39:40 -08:00
|
|
|
if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-oleobject")))) {
|
2007-03-22 10:30:00 -07:00
|
|
|
aType.AssignLiteral("application/x-oleobject");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-02-10 05:39:40 -08:00
|
|
|
if (NS_SUCCEEDED(IsPluginEnabledForType(NS_LITERAL_CSTRING("application/oleobject")))) {
|
2007-03-22 10:30:00 -07:00
|
|
|
aType.AssignLiteral("application/oleobject");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
void
|
|
|
|
nsObjectLoadingContent::GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI)
|
|
|
|
{
|
|
|
|
// We want to use swap(); since this is just called from this file,
|
|
|
|
// we can assert this (callers use comptrs)
|
|
|
|
NS_PRECONDITION(*aURI == nsnull, "URI must be inited to zero");
|
|
|
|
|
|
|
|
// For plugins, the codebase attribute is the base URI
|
|
|
|
nsCOMPtr<nsIURI> baseURI = thisContent->GetBaseURI();
|
|
|
|
nsAutoString codebase;
|
|
|
|
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase,
|
|
|
|
codebase);
|
|
|
|
if (!codebase.IsEmpty()) {
|
|
|
|
nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
|
|
|
|
thisContent->OwnerDoc(),
|
|
|
|
baseURI);
|
|
|
|
} else {
|
|
|
|
baseURI.swap(*aURI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
nsObjectFrame*
|
|
|
|
nsObjectLoadingContent::GetExistingFrame()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2012-01-31 13:55:54 -08:00
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
nsIFrame* frame = thisContent->GetPrimaryFrame();
|
2009-01-12 11:20:59 -08:00
|
|
|
nsIObjectFrame* objFrame = do_QueryFrame(frame);
|
2012-01-31 13:55:54 -08:00
|
|
|
return static_cast<nsObjectFrame*>(objFrame);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
void
|
|
|
|
nsObjectLoadingContent::HandleBeingBlockedByContentPolicy(nsresult aStatus,
|
|
|
|
PRInt16 aRetval)
|
|
|
|
{
|
|
|
|
// Must call UnloadContent first, as it overwrites
|
|
|
|
// mSuppressed/mUserDisabled. It also takes care of setting the type to
|
|
|
|
// eType_Null.
|
|
|
|
UnloadContent();
|
|
|
|
if (NS_SUCCEEDED(aStatus)) {
|
|
|
|
if (aRetval == nsIContentPolicy::REJECT_TYPE) {
|
|
|
|
mUserDisabled = true;
|
|
|
|
} else if (aRetval == nsIContentPolicy::REJECT_SERVER) {
|
|
|
|
mSuppressed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PluginSupportState
|
|
|
|
nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
|
|
|
|
const nsCString& aContentType)
|
|
|
|
{
|
|
|
|
if (!aContent->IsHTML()) {
|
|
|
|
return ePluginOtherState;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aContent->Tag() == nsGkAtoms::embed ||
|
|
|
|
aContent->Tag() == nsGkAtoms::applet) {
|
|
|
|
return GetPluginDisabledState(aContentType);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasAlternateContent = false;
|
|
|
|
|
|
|
|
// Search for a child <param> with a pluginurl name
|
|
|
|
for (nsIContent* child = aContent->GetFirstChild();
|
|
|
|
child;
|
|
|
|
child = child->GetNextSibling()) {
|
|
|
|
if (child->IsHTML(nsGkAtoms::param)) {
|
|
|
|
if (child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
|
|
|
|
NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) {
|
|
|
|
return GetPluginDisabledState(aContentType);
|
|
|
|
}
|
|
|
|
} else if (!hasAlternateContent) {
|
|
|
|
hasAlternateContent =
|
|
|
|
nsStyleUtil::IsSignificantChild(child, true, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PluginSupportState pluginDisabledState = GetPluginDisabledState(aContentType);
|
|
|
|
if (pluginDisabledState == ePluginClickToPlay ||
|
|
|
|
pluginDisabledState == ePluginVulnerableUpdatable ||
|
|
|
|
pluginDisabledState == ePluginVulnerableNoUpdate) {
|
|
|
|
return pluginDisabledState;
|
|
|
|
} else if (hasAlternateContent) {
|
|
|
|
return ePluginOtherState;
|
|
|
|
} else {
|
|
|
|
return pluginDisabledState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PluginSupportState
|
|
|
|
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
|
|
|
|
{
|
|
|
|
nsresult rv = IsPluginEnabledForType(aContentType);
|
|
|
|
if (rv == NS_ERROR_PLUGIN_DISABLED) {
|
|
|
|
return ePluginDisabled;
|
|
|
|
}
|
|
|
|
if (rv == NS_ERROR_PLUGIN_CLICKTOPLAY) {
|
|
|
|
PRUint32 state;
|
|
|
|
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
|
|
|
|
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
|
|
|
|
if (pluginHost) {
|
|
|
|
rv = pluginHost->GetBlocklistStateForType(aContentType.get(), &state);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (state == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
|
|
|
|
return ePluginVulnerableUpdatable;
|
|
|
|
} else if (state == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
|
|
|
|
return ePluginVulnerableNoUpdate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ePluginClickToPlay;
|
|
|
|
}
|
|
|
|
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED) {
|
|
|
|
return ePluginBlocklisted;
|
|
|
|
}
|
|
|
|
return ePluginUnsupported;
|
|
|
|
}
|
|
|
|
|
2009-12-10 20:02:13 -08:00
|
|
|
void
|
|
|
|
nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
|
|
|
|
{
|
|
|
|
nsImageLoadingContent::CreateStaticImageClone(aDest);
|
|
|
|
|
|
|
|
aDest->mType = mType;
|
|
|
|
nsObjectLoadingContent* thisObj = const_cast<nsObjectLoadingContent*>(this);
|
|
|
|
if (thisObj->mPrintFrame.IsAlive()) {
|
|
|
|
aDest->mPrintFrame = thisObj->mPrintFrame;
|
|
|
|
} else {
|
2012-01-31 13:55:54 -08:00
|
|
|
aDest->mPrintFrame = const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame();
|
2009-12-10 20:02:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mFrameLoader) {
|
|
|
|
nsCOMPtr<nsIContent> content =
|
2011-10-01 10:14:35 -07:00
|
|
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(aDest));
|
2011-10-17 07:59:28 -07:00
|
|
|
nsFrameLoader* fl = nsFrameLoader::Create(content->AsElement(), false);
|
2009-12-10 20:02:13 -08:00
|
|
|
if (fl) {
|
|
|
|
aDest->mFrameLoader = fl;
|
|
|
|
mFrameLoader->CreateStaticClone(fl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame)
|
|
|
|
{
|
|
|
|
*aFrame = mPrintFrame.GetFrame();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-01-13 08:42:41 -08:00
|
|
|
NS_IMETHODIMP
|
2010-03-16 22:10:08 -07:00
|
|
|
nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
|
2010-03-24 14:22:04 -07:00
|
|
|
const nsAString& pluginDumpID,
|
|
|
|
const nsAString& browserDumpID,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool submittedCrashReport)
|
2010-01-13 08:42:41 -08:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
AutoNotifier notifier(this, true);
|
|
|
|
UnloadContent();
|
|
|
|
mFallbackReason = ePluginCrashed;
|
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
2010-03-16 22:10:08 -07:00
|
|
|
|
|
|
|
// Note that aPluginTag in invalidated after we're called, so copy
|
|
|
|
// out any data we need now.
|
|
|
|
nsCAutoString pluginName;
|
|
|
|
aPluginTag->GetName(pluginName);
|
2010-04-08 00:45:00 -07:00
|
|
|
nsCAutoString pluginFilename;
|
|
|
|
aPluginTag->GetFilename(pluginFilename);
|
2010-03-16 22:10:08 -07:00
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIRunnable> ev = new nsPluginCrashedEvent(thisContent,
|
|
|
|
pluginDumpID,
|
|
|
|
browserDumpID,
|
|
|
|
NS_ConvertUTF8toUTF16(pluginName),
|
|
|
|
NS_ConvertUTF8toUTF16(pluginFilename),
|
|
|
|
submittedCrashReport);
|
2010-02-09 17:05:31 -08:00
|
|
|
nsresult rv = NS_DispatchToCurrentThread(ev);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("failed to dispatch nsPluginCrashedEvent");
|
|
|
|
}
|
2010-01-13 08:42:41 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2011-12-10 09:23:05 -08:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::SyncStartPluginInstance()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
|
|
|
|
"Must be able to run script in order to instantiate a plugin instance!");
|
|
|
|
|
2012-02-13 13:26:41 -08:00
|
|
|
// Don't even attempt to start an instance unless the content is in
|
|
|
|
// the document.
|
|
|
|
nsCOMPtr<nsIContent> thisContent =
|
|
|
|
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
2012-01-31 13:55:54 -08:00
|
|
|
if (!thisContent->IsInDoc()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2012-02-08 15:15:16 -08:00
|
|
|
nsCOMPtr<nsIURI> kungFuURIGrip(mURI);
|
2012-02-13 13:26:41 -08:00
|
|
|
nsCString contentType(mContentType);
|
2012-07-25 13:39:01 -07:00
|
|
|
return InstantiatePluginInstance(contentType.get(), mURI.get());
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::AsyncStartPluginInstance()
|
|
|
|
{
|
|
|
|
// OK to have an instance already.
|
|
|
|
if (mInstanceOwner) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
|
|
|
nsIDocument* doc = thisContent->OwnerDoc();
|
|
|
|
if (doc->IsStaticDocument() || doc->IsBeingUsedAsImage()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We always start plugins on a runnable.
|
|
|
|
// We don't want a script blocker on the stack during instantiation.
|
|
|
|
nsCOMPtr<nsIRunnable> event = new nsAsyncInstantiateEvent(this);
|
|
|
|
if (!event) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
nsresult rv = NS_DispatchToCurrentThread(event);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// Remember this event. This is a weak reference that will be cleared
|
|
|
|
// when the event runs.
|
|
|
|
mPendingInstantiateEvent = event;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2012-03-12 09:48:27 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::GetSrcURI(nsIURI** aURI)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aURI = mURI);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
static bool
|
2012-05-25 15:34:11 -07:00
|
|
|
DoDelayedStop(nsPluginInstanceOwner* aInstanceOwner,
|
|
|
|
nsObjectLoadingContent* aContent,
|
|
|
|
bool aDelayedStop)
|
2012-01-31 13:55:54 -08:00
|
|
|
{
|
|
|
|
#if (MOZ_PLATFORM_MAEMO==5)
|
|
|
|
// Don't delay stop on Maemo/Hildon (bug 530739).
|
|
|
|
if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash"))
|
|
|
|
return false;
|
|
|
|
#endif
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
// Don't delay stopping QuickTime (bug 425157), Flip4Mac (bug 426524),
|
|
|
|
// XStandard (bug 430219), CMISS Zinc (bug 429604).
|
|
|
|
if (aDelayedStop
|
|
|
|
#if !(defined XP_WIN || defined MOZ_X11)
|
|
|
|
&& !aInstanceOwner->MatchPluginName("QuickTime")
|
|
|
|
&& !aInstanceOwner->MatchPluginName("Flip4Mac")
|
|
|
|
&& !aInstanceOwner->MatchPluginName("XStandard plugin")
|
|
|
|
&& !aInstanceOwner->MatchPluginName("CMISS Zinc Plugin")
|
|
|
|
#endif
|
|
|
|
) {
|
2012-05-25 15:34:11 -07:00
|
|
|
nsCOMPtr<nsIRunnable> evt =
|
|
|
|
new nsStopPluginRunnable(aInstanceOwner, aContent);
|
2012-01-31 13:55:54 -08:00
|
|
|
NS_DispatchToCurrentThread(evt);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-05-25 15:34:11 -07:00
|
|
|
nsObjectLoadingContent::DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner,
|
|
|
|
bool aDelayedStop,
|
|
|
|
bool aForcedReentry)
|
|
|
|
{
|
|
|
|
// DoStopPlugin can process events and there may be pending InDocCheckEvent
|
|
|
|
// events which can drop in underneath us and destroy the instance we are
|
2012-07-25 13:39:01 -07:00
|
|
|
// about to destroy unless we prevent that with the mIsStopping flag.
|
2012-05-25 15:34:11 -07:00
|
|
|
// (aForcedReentry is only true from the callback of an earlier delayed stop)
|
|
|
|
if (mIsStopping && !aForcedReentry) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mIsStopping = true;
|
|
|
|
|
2012-05-31 05:44:10 -07:00
|
|
|
nsRefPtr<nsPluginInstanceOwner> kungFuDeathGrip(aInstanceOwner);
|
2012-01-31 13:55:54 -08:00
|
|
|
nsRefPtr<nsNPAPIPluginInstance> inst;
|
|
|
|
aInstanceOwner->GetInstance(getter_AddRefs(inst));
|
|
|
|
if (inst) {
|
2012-05-25 15:34:11 -07:00
|
|
|
if (DoDelayedStop(aInstanceOwner, this, aDelayedStop)) {
|
2012-01-31 13:55:54 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(XP_MACOSX)
|
|
|
|
aInstanceOwner->HidePluginWindow();
|
|
|
|
#endif
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
|
|
|
NS_ASSERTION(pluginHost, "Without a pluginHost, how can we have an instance to destroy?");
|
|
|
|
static_cast<nsPluginHost*>(pluginHost.get())->StopPluginInstance(inst);
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
aInstanceOwner->Destroy();
|
2012-07-25 13:39:01 -07:00
|
|
|
mIsStopping = false;
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::StopPluginInstance()
|
|
|
|
{
|
|
|
|
if (!mInstanceOwner) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
DisconnectFrame();
|
|
|
|
|
|
|
|
bool delayedStop = false;
|
|
|
|
#ifdef XP_WIN
|
|
|
|
// Force delayed stop for Real plugin only; see bug 420886, 426852.
|
|
|
|
nsRefPtr<nsNPAPIPluginInstance> inst;
|
|
|
|
mInstanceOwner->GetInstance(getter_AddRefs(inst));
|
|
|
|
if (inst) {
|
|
|
|
const char* mime = nsnull;
|
|
|
|
if (NS_SUCCEEDED(inst->GetMIMEType(&mime)) && mime) {
|
|
|
|
if (strcmp(mime, "audio/x-pn-realaudio-plugin") == 0) {
|
|
|
|
delayedStop = true;
|
2012-07-25 13:39:01 -07:00
|
|
|
}
|
2012-01-31 13:55:54 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-05-25 15:34:11 -07:00
|
|
|
DoStopPlugin(mInstanceOwner, delayedStop);
|
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
mInstanceOwner = nsnull;
|
2012-05-25 15:34:11 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectLoadingContent::NotifyContentObjectWrapper()
|
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
2012-01-31 13:55:54 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> doc = thisContent->GetDocument();
|
|
|
|
if (!doc)
|
|
|
|
return;
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
nsIScriptGlobalObject *sgo = doc->GetScopeObject();
|
|
|
|
if (!sgo)
|
|
|
|
return;
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
nsIScriptContext *scx = sgo->GetContext();
|
|
|
|
if (!scx)
|
|
|
|
return;
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
JSContext *cx = scx->GetNativeContext();
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
|
|
|
nsContentUtils::XPConnect()->
|
|
|
|
GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), thisContent,
|
|
|
|
NS_GET_IID(nsISupports),
|
|
|
|
getter_AddRefs(wrapper));
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
if (!wrapper) {
|
|
|
|
// Nothing to do here if there's no wrapper for mContent. The proto
|
|
|
|
// chain will be fixed appropriately when the wrapper is created.
|
|
|
|
return;
|
|
|
|
}
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
JSObject *obj = nsnull;
|
|
|
|
nsresult rv = wrapper->GetJSObject(&obj);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
2012-07-25 13:39:01 -07:00
|
|
|
|
2012-01-31 13:55:54 -08:00
|
|
|
nsHTMLPluginObjElementSH::SetupProtoChain(wrapper, cx, obj);
|
|
|
|
}
|
|
|
|
|
2011-12-10 09:23:05 -08:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectLoadingContent::PlayPlugin()
|
|
|
|
{
|
|
|
|
if (!nsContentUtils::IsCallerChrome())
|
|
|
|
return NS_OK;
|
|
|
|
|
2012-07-25 13:39:01 -07:00
|
|
|
mCTPPlayable = true;
|
|
|
|
return LoadObject(mURI, true, mContentType, true);
|
2011-12-10 09:23:05 -08:00
|
|
|
}
|
2012-03-28 08:53:56 -07:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-07-25 13:39:01 -07:00
|
|
|
nsObjectLoadingContent::GetActivated(bool* aActivated)
|
2012-03-28 08:53:56 -07:00
|
|
|
{
|
2012-07-25 13:39:01 -07:00
|
|
|
*aActivated = mActivated;
|
2012-03-28 08:53:56 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|