dom/base/nsPluginArray.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsPluginArray.h"
michael@0 7
michael@0 8 #include "mozilla/Preferences.h"
michael@0 9 #include "mozilla/dom/PluginArrayBinding.h"
michael@0 10 #include "mozilla/dom/PluginBinding.h"
michael@0 11
michael@0 12 #include "nsCharSeparatedTokenizer.h"
michael@0 13 #include "nsMimeTypeArray.h"
michael@0 14 #include "Navigator.h"
michael@0 15 #include "nsIDocShell.h"
michael@0 16 #include "nsIWebNavigation.h"
michael@0 17 #include "nsPluginHost.h"
michael@0 18 #include "nsPluginTags.h"
michael@0 19 #include "nsIObserverService.h"
michael@0 20 #include "nsIWeakReference.h"
michael@0 21 #include "mozilla/Services.h"
michael@0 22 #include "nsIInterfaceRequestorUtils.h"
michael@0 23
michael@0 24 using namespace mozilla;
michael@0 25 using namespace mozilla::dom;
michael@0 26
michael@0 27 nsPluginArray::nsPluginArray(nsPIDOMWindow* aWindow)
michael@0 28 : mWindow(aWindow)
michael@0 29 {
michael@0 30 SetIsDOMBinding();
michael@0 31 }
michael@0 32
michael@0 33 void
michael@0 34 nsPluginArray::Init()
michael@0 35 {
michael@0 36 nsCOMPtr<nsIObserverService> obsService =
michael@0 37 mozilla::services::GetObserverService();
michael@0 38 if (obsService) {
michael@0 39 obsService->AddObserver(this, "plugin-info-updated", true);
michael@0 40 }
michael@0 41 }
michael@0 42
michael@0 43 nsPluginArray::~nsPluginArray()
michael@0 44 {
michael@0 45 }
michael@0 46
michael@0 47 nsPIDOMWindow*
michael@0 48 nsPluginArray::GetParentObject() const
michael@0 49 {
michael@0 50 MOZ_ASSERT(mWindow);
michael@0 51 return mWindow;
michael@0 52 }
michael@0 53
michael@0 54 JSObject*
michael@0 55 nsPluginArray::WrapObject(JSContext* aCx)
michael@0 56 {
michael@0 57 return PluginArrayBinding::Wrap(aCx, this);
michael@0 58 }
michael@0 59
michael@0 60 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPluginArray)
michael@0 61 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPluginArray)
michael@0 62 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPluginArray)
michael@0 63 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 64 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
michael@0 65 NS_INTERFACE_MAP_ENTRY(nsIObserver)
michael@0 66 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
michael@0 67 NS_INTERFACE_MAP_END
michael@0 68
michael@0 69 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(nsPluginArray,
michael@0 70 mWindow,
michael@0 71 mPlugins,
michael@0 72 mHiddenPlugins)
michael@0 73
michael@0 74 static void
michael@0 75 GetPluginMimeTypes(const nsTArray<nsRefPtr<nsPluginElement> >& aPlugins,
michael@0 76 nsTArray<nsRefPtr<nsMimeType> >& aMimeTypes)
michael@0 77 {
michael@0 78 for (uint32_t i = 0; i < aPlugins.Length(); ++i) {
michael@0 79 nsPluginElement *plugin = aPlugins[i];
michael@0 80 aMimeTypes.AppendElements(plugin->MimeTypes());
michael@0 81 }
michael@0 82 }
michael@0 83
michael@0 84 void
michael@0 85 nsPluginArray::GetMimeTypes(nsTArray<nsRefPtr<nsMimeType> >& aMimeTypes,
michael@0 86 nsTArray<nsRefPtr<nsMimeType> >& aHiddenMimeTypes)
michael@0 87 {
michael@0 88 aMimeTypes.Clear();
michael@0 89 aHiddenMimeTypes.Clear();
michael@0 90
michael@0 91 if (!AllowPlugins()) {
michael@0 92 return;
michael@0 93 }
michael@0 94
michael@0 95 EnsurePlugins();
michael@0 96
michael@0 97 GetPluginMimeTypes(mPlugins, aMimeTypes);
michael@0 98 GetPluginMimeTypes(mHiddenPlugins, aHiddenMimeTypes);
michael@0 99 }
michael@0 100
michael@0 101 nsPluginElement*
michael@0 102 nsPluginArray::Item(uint32_t aIndex)
michael@0 103 {
michael@0 104 bool unused;
michael@0 105 return IndexedGetter(aIndex, unused);
michael@0 106 }
michael@0 107
michael@0 108 nsPluginElement*
michael@0 109 nsPluginArray::NamedItem(const nsAString& aName)
michael@0 110 {
michael@0 111 bool unused;
michael@0 112 return NamedGetter(aName, unused);
michael@0 113 }
michael@0 114
michael@0 115 void
michael@0 116 nsPluginArray::Refresh(bool aReloadDocuments)
michael@0 117 {
michael@0 118 nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
michael@0 119
michael@0 120 if(!AllowPlugins() || !pluginHost) {
michael@0 121 return;
michael@0 122 }
michael@0 123
michael@0 124 // NS_ERROR_PLUGINS_PLUGINSNOTCHANGED on reloading plugins indicates
michael@0 125 // that plugins did not change and was not reloaded
michael@0 126 if (pluginHost->ReloadPlugins() ==
michael@0 127 NS_ERROR_PLUGINS_PLUGINSNOTCHANGED) {
michael@0 128 nsTArray<nsRefPtr<nsPluginTag> > newPluginTags;
michael@0 129 pluginHost->GetPlugins(newPluginTags);
michael@0 130
michael@0 131 // Check if the number of plugins we know about are different from
michael@0 132 // the number of plugin tags the plugin host knows about. If the
michael@0 133 // lengths are different, we refresh. This is safe because we're
michael@0 134 // notified for every plugin enabling/disabling event that
michael@0 135 // happens, and therefore the lengths will be in sync only when
michael@0 136 // the both arrays contain the same plugin tags (though as
michael@0 137 // different types).
michael@0 138 uint32_t pluginCount = mPlugins.Length() + mHiddenPlugins.Length();
michael@0 139 if (newPluginTags.Length() == pluginCount) {
michael@0 140 return;
michael@0 141 }
michael@0 142 }
michael@0 143
michael@0 144 mPlugins.Clear();
michael@0 145 mHiddenPlugins.Clear();
michael@0 146
michael@0 147 nsCOMPtr<nsIDOMNavigator> navigator;
michael@0 148 mWindow->GetNavigator(getter_AddRefs(navigator));
michael@0 149
michael@0 150 if (!navigator) {
michael@0 151 return;
michael@0 152 }
michael@0 153
michael@0 154 static_cast<mozilla::dom::Navigator*>(navigator.get())->RefreshMIMEArray();
michael@0 155
michael@0 156 nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(mWindow);
michael@0 157 if (aReloadDocuments && webNav) {
michael@0 158 webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
michael@0 159 }
michael@0 160 }
michael@0 161
michael@0 162 nsPluginElement*
michael@0 163 nsPluginArray::IndexedGetter(uint32_t aIndex, bool &aFound)
michael@0 164 {
michael@0 165 aFound = false;
michael@0 166
michael@0 167 if (!AllowPlugins()) {
michael@0 168 return nullptr;
michael@0 169 }
michael@0 170
michael@0 171 EnsurePlugins();
michael@0 172
michael@0 173 aFound = aIndex < mPlugins.Length();
michael@0 174
michael@0 175 return aFound ? mPlugins[aIndex] : nullptr;
michael@0 176 }
michael@0 177
michael@0 178 void
michael@0 179 nsPluginArray::Invalidate()
michael@0 180 {
michael@0 181 nsCOMPtr<nsIObserverService> obsService =
michael@0 182 mozilla::services::GetObserverService();
michael@0 183 if (obsService) {
michael@0 184 obsService->RemoveObserver(this, "plugin-info-updated");
michael@0 185 }
michael@0 186 }
michael@0 187
michael@0 188 static nsPluginElement*
michael@0 189 FindPlugin(const nsTArray<nsRefPtr<nsPluginElement> >& aPlugins,
michael@0 190 const nsAString& aName)
michael@0 191 {
michael@0 192 for (uint32_t i = 0; i < aPlugins.Length(); ++i) {
michael@0 193 nsAutoString pluginName;
michael@0 194 nsPluginElement* plugin = aPlugins[i];
michael@0 195 plugin->GetName(pluginName);
michael@0 196
michael@0 197 if (pluginName.Equals(aName)) {
michael@0 198 return plugin;
michael@0 199 }
michael@0 200 }
michael@0 201
michael@0 202 return nullptr;
michael@0 203 }
michael@0 204
michael@0 205 nsPluginElement*
michael@0 206 nsPluginArray::NamedGetter(const nsAString& aName, bool &aFound)
michael@0 207 {
michael@0 208 aFound = false;
michael@0 209
michael@0 210 if (!AllowPlugins()) {
michael@0 211 return nullptr;
michael@0 212 }
michael@0 213
michael@0 214 EnsurePlugins();
michael@0 215
michael@0 216 nsPluginElement* plugin = FindPlugin(mPlugins, aName);
michael@0 217 if (!plugin) {
michael@0 218 plugin = FindPlugin(mHiddenPlugins, aName);
michael@0 219 }
michael@0 220
michael@0 221 aFound = (plugin != nullptr);
michael@0 222 return plugin;
michael@0 223 }
michael@0 224
michael@0 225 bool
michael@0 226 nsPluginArray::NameIsEnumerable(const nsAString& aName)
michael@0 227 {
michael@0 228 return true;
michael@0 229 }
michael@0 230
michael@0 231 uint32_t
michael@0 232 nsPluginArray::Length()
michael@0 233 {
michael@0 234 if (!AllowPlugins()) {
michael@0 235 return 0;
michael@0 236 }
michael@0 237
michael@0 238 EnsurePlugins();
michael@0 239
michael@0 240 return mPlugins.Length();
michael@0 241 }
michael@0 242
michael@0 243 void
michael@0 244 nsPluginArray::GetSupportedNames(unsigned, nsTArray<nsString>& aRetval)
michael@0 245 {
michael@0 246 aRetval.Clear();
michael@0 247
michael@0 248 if (!AllowPlugins()) {
michael@0 249 return;
michael@0 250 }
michael@0 251
michael@0 252 for (uint32_t i = 0; i < mPlugins.Length(); ++i) {
michael@0 253 nsAutoString pluginName;
michael@0 254 mPlugins[i]->GetName(pluginName);
michael@0 255
michael@0 256 aRetval.AppendElement(pluginName);
michael@0 257 }
michael@0 258 }
michael@0 259
michael@0 260 NS_IMETHODIMP
michael@0 261 nsPluginArray::Observe(nsISupports *aSubject, const char *aTopic,
michael@0 262 const char16_t *aData) {
michael@0 263 if (!nsCRT::strcmp(aTopic, "plugin-info-updated")) {
michael@0 264 Refresh(false);
michael@0 265 }
michael@0 266
michael@0 267 return NS_OK;
michael@0 268 }
michael@0 269
michael@0 270 bool
michael@0 271 nsPluginArray::AllowPlugins() const
michael@0 272 {
michael@0 273 nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mWindow);
michael@0 274
michael@0 275 return docShell && docShell->PluginsAllowedInCurrentDoc();
michael@0 276 }
michael@0 277
michael@0 278 static bool
michael@0 279 HasStringPrefix(const nsCString& str, const nsACString& prefix) {
michael@0 280 return str.Compare(prefix.BeginReading(), false, prefix.Length()) == 0;
michael@0 281 }
michael@0 282
michael@0 283 static bool
michael@0 284 IsPluginEnumerable(const nsTArray<nsCString>& enumerableNames,
michael@0 285 const nsPluginTag* pluginTag)
michael@0 286 {
michael@0 287 const nsCString& pluginName = pluginTag->mName;
michael@0 288
michael@0 289 const uint32_t length = enumerableNames.Length();
michael@0 290 for (uint32_t i = 0; i < length; i++) {
michael@0 291 const nsCString& name = enumerableNames[i];
michael@0 292 if (HasStringPrefix(pluginName, name)) {
michael@0 293 return true; // don't hide plugin
michael@0 294 }
michael@0 295 }
michael@0 296
michael@0 297 return false; // hide plugin!
michael@0 298 }
michael@0 299
michael@0 300 void
michael@0 301 nsPluginArray::EnsurePlugins()
michael@0 302 {
michael@0 303 if (!mPlugins.IsEmpty() || !mHiddenPlugins.IsEmpty()) {
michael@0 304 // We already have an array of plugin elements.
michael@0 305 return;
michael@0 306 }
michael@0 307
michael@0 308 nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
michael@0 309 if (!pluginHost) {
michael@0 310 // We have no plugin host.
michael@0 311 return;
michael@0 312 }
michael@0 313
michael@0 314 nsTArray<nsRefPtr<nsPluginTag> > pluginTags;
michael@0 315 pluginHost->GetPlugins(pluginTags);
michael@0 316
michael@0 317 nsTArray<nsCString> enumerableNames;
michael@0 318
michael@0 319 const nsAdoptingCString& enumerableNamesPref =
michael@0 320 Preferences::GetCString("plugins.enumerable_names");
michael@0 321
michael@0 322 bool disablePluginHiding = !enumerableNamesPref ||
michael@0 323 enumerableNamesPref.EqualsLiteral("*");
michael@0 324
michael@0 325 if (!disablePluginHiding) {
michael@0 326 nsCCharSeparatedTokenizer tokens(enumerableNamesPref, ',');
michael@0 327 while (tokens.hasMoreTokens()) {
michael@0 328 const nsCSubstring& token = tokens.nextToken();
michael@0 329 if (!token.IsEmpty()) {
michael@0 330 enumerableNames.AppendElement(token);
michael@0 331 }
michael@0 332 }
michael@0 333 }
michael@0 334
michael@0 335 // need to wrap each of these with a nsPluginElement, which is
michael@0 336 // scriptable.
michael@0 337 for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
michael@0 338 nsPluginTag* pluginTag = pluginTags[i];
michael@0 339
michael@0 340 // Add the plugin to the list of hidden plugins or non-hidden plugins?
michael@0 341 nsTArray<nsRefPtr<nsPluginElement> >& pluginArray =
michael@0 342 (disablePluginHiding || IsPluginEnumerable(enumerableNames, pluginTag))
michael@0 343 ? mPlugins
michael@0 344 : mHiddenPlugins;
michael@0 345
michael@0 346 pluginArray.AppendElement(new nsPluginElement(mWindow, pluginTag));
michael@0 347 }
michael@0 348 }
michael@0 349
michael@0 350 // nsPluginElement implementation.
michael@0 351
michael@0 352 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPluginElement)
michael@0 353 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPluginElement)
michael@0 354 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPluginElement)
michael@0 355 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 356 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 357 NS_INTERFACE_MAP_END
michael@0 358
michael@0 359 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(nsPluginElement, mWindow, mMimeTypes)
michael@0 360
michael@0 361 nsPluginElement::nsPluginElement(nsPIDOMWindow* aWindow,
michael@0 362 nsPluginTag* aPluginTag)
michael@0 363 : mWindow(aWindow),
michael@0 364 mPluginTag(aPluginTag)
michael@0 365 {
michael@0 366 SetIsDOMBinding();
michael@0 367 }
michael@0 368
michael@0 369 nsPIDOMWindow*
michael@0 370 nsPluginElement::GetParentObject() const
michael@0 371 {
michael@0 372 MOZ_ASSERT(mWindow);
michael@0 373 return mWindow;
michael@0 374 }
michael@0 375
michael@0 376 JSObject*
michael@0 377 nsPluginElement::WrapObject(JSContext* aCx)
michael@0 378 {
michael@0 379 return PluginBinding::Wrap(aCx, this);
michael@0 380 }
michael@0 381
michael@0 382 void
michael@0 383 nsPluginElement::GetDescription(nsString& retval) const
michael@0 384 {
michael@0 385 CopyUTF8toUTF16(mPluginTag->mDescription, retval);
michael@0 386 }
michael@0 387
michael@0 388 void
michael@0 389 nsPluginElement::GetFilename(nsString& retval) const
michael@0 390 {
michael@0 391 CopyUTF8toUTF16(mPluginTag->mFileName, retval);
michael@0 392 }
michael@0 393
michael@0 394 void
michael@0 395 nsPluginElement::GetVersion(nsString& retval) const
michael@0 396 {
michael@0 397 CopyUTF8toUTF16(mPluginTag->mVersion, retval);
michael@0 398 }
michael@0 399
michael@0 400 void
michael@0 401 nsPluginElement::GetName(nsString& retval) const
michael@0 402 {
michael@0 403 CopyUTF8toUTF16(mPluginTag->mName, retval);
michael@0 404 }
michael@0 405
michael@0 406 nsMimeType*
michael@0 407 nsPluginElement::Item(uint32_t aIndex)
michael@0 408 {
michael@0 409 EnsurePluginMimeTypes();
michael@0 410
michael@0 411 return mMimeTypes.SafeElementAt(aIndex);
michael@0 412 }
michael@0 413
michael@0 414 nsMimeType*
michael@0 415 nsPluginElement::NamedItem(const nsAString& aName)
michael@0 416 {
michael@0 417 bool unused;
michael@0 418 return NamedGetter(aName, unused);
michael@0 419 }
michael@0 420
michael@0 421 nsMimeType*
michael@0 422 nsPluginElement::IndexedGetter(uint32_t aIndex, bool &aFound)
michael@0 423 {
michael@0 424 EnsurePluginMimeTypes();
michael@0 425
michael@0 426 aFound = aIndex < mMimeTypes.Length();
michael@0 427
michael@0 428 return aFound ? mMimeTypes[aIndex] : nullptr;
michael@0 429 }
michael@0 430
michael@0 431 nsMimeType*
michael@0 432 nsPluginElement::NamedGetter(const nsAString& aName, bool &aFound)
michael@0 433 {
michael@0 434 EnsurePluginMimeTypes();
michael@0 435
michael@0 436 aFound = false;
michael@0 437
michael@0 438 for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
michael@0 439 if (mMimeTypes[i]->Type().Equals(aName)) {
michael@0 440 aFound = true;
michael@0 441
michael@0 442 return mMimeTypes[i];
michael@0 443 }
michael@0 444 }
michael@0 445
michael@0 446 return nullptr;
michael@0 447 }
michael@0 448
michael@0 449 bool
michael@0 450 nsPluginElement::NameIsEnumerable(const nsAString& aName)
michael@0 451 {
michael@0 452 return true;
michael@0 453 }
michael@0 454
michael@0 455 uint32_t
michael@0 456 nsPluginElement::Length()
michael@0 457 {
michael@0 458 EnsurePluginMimeTypes();
michael@0 459
michael@0 460 return mMimeTypes.Length();
michael@0 461 }
michael@0 462
michael@0 463 void
michael@0 464 nsPluginElement::GetSupportedNames(unsigned, nsTArray<nsString>& retval)
michael@0 465 {
michael@0 466 EnsurePluginMimeTypes();
michael@0 467
michael@0 468 for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
michael@0 469 retval.AppendElement(mMimeTypes[i]->Type());
michael@0 470 }
michael@0 471 }
michael@0 472
michael@0 473 nsTArray<nsRefPtr<nsMimeType> >&
michael@0 474 nsPluginElement::MimeTypes()
michael@0 475 {
michael@0 476 EnsurePluginMimeTypes();
michael@0 477
michael@0 478 return mMimeTypes;
michael@0 479 }
michael@0 480
michael@0 481 void
michael@0 482 nsPluginElement::EnsurePluginMimeTypes()
michael@0 483 {
michael@0 484 if (!mMimeTypes.IsEmpty()) {
michael@0 485 return;
michael@0 486 }
michael@0 487
michael@0 488 for (uint32_t i = 0; i < mPluginTag->mMimeTypes.Length(); ++i) {
michael@0 489 NS_ConvertUTF8toUTF16 type(mPluginTag->mMimeTypes[i]);
michael@0 490 mMimeTypes.AppendElement(new nsMimeType(mWindow, this, i, type));
michael@0 491 }
michael@0 492 }

mercurial