diff options
Diffstat (limited to 'dom/base/TabGroup.cpp')
-rw-r--r-- | dom/base/TabGroup.cpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/dom/base/TabGroup.cpp b/dom/base/TabGroup.cpp new file mode 100644 index 000000000..de67bcb78 --- /dev/null +++ b/dom/base/TabGroup.cpp @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "mozilla/dom/TabGroup.h" + +#include "mozilla/dom/DocGroup.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/Telemetry.h" +#include "mozilla/ThrottledEventQueue.h" +#include "nsIDocShell.h" +#include "nsIEffectiveTLDService.h" +#include "nsIURI.h" + +namespace mozilla { +namespace dom { + +static StaticRefPtr<TabGroup> sChromeTabGroup; + +TabGroup::TabGroup(bool aIsChrome) +{ + // Do not throttle runnables from chrome windows. In theory we should + // not have abuse issues from these windows and many browser chrome + // tests have races that fail if we do throttle chrome runnables. + if (aIsChrome) { + MOZ_ASSERT(!sChromeTabGroup); + return; + } + + nsCOMPtr<nsIThread> mainThread; + NS_GetMainThread(getter_AddRefs(mainThread)); + MOZ_DIAGNOSTIC_ASSERT(mainThread); + + // This may return nullptr during xpcom shutdown. This is ok as we + // do not guarantee a ThrottledEventQueue will be present. + mThrottledEventQueue = ThrottledEventQueue::Create(mainThread); +} + +TabGroup::~TabGroup() +{ + MOZ_ASSERT(mDocGroups.IsEmpty()); + MOZ_ASSERT(mWindows.IsEmpty()); +} + +TabGroup* +TabGroup::GetChromeTabGroup() +{ + if (!sChromeTabGroup) { + sChromeTabGroup = new TabGroup(true /* chrome tab group */); + ClearOnShutdown(&sChromeTabGroup); + } + return sChromeTabGroup; +} + +already_AddRefed<DocGroup> +TabGroup::GetDocGroup(const nsACString& aKey) +{ + RefPtr<DocGroup> docGroup(mDocGroups.GetEntry(aKey)->mDocGroup); + return docGroup.forget(); +} + +already_AddRefed<DocGroup> +TabGroup::AddDocument(const nsACString& aKey, nsIDocument* aDocument) +{ + HashEntry* entry = mDocGroups.PutEntry(aKey); + RefPtr<DocGroup> docGroup; + if (entry->mDocGroup) { + docGroup = entry->mDocGroup; + } else { + docGroup = new DocGroup(this, aKey); + entry->mDocGroup = docGroup; + } + + // Make sure that the hashtable was updated and now contains the correct value + MOZ_ASSERT(RefPtr<DocGroup>(GetDocGroup(aKey)) == docGroup); + + docGroup->mDocuments.AppendElement(aDocument); + + return docGroup.forget(); +} + +/* static */ already_AddRefed<TabGroup> +TabGroup::Join(nsPIDOMWindowOuter* aWindow, TabGroup* aTabGroup) +{ + RefPtr<TabGroup> tabGroup = aTabGroup; + if (!tabGroup) { + tabGroup = new TabGroup(); + } + MOZ_ASSERT(!tabGroup->mWindows.Contains(aWindow)); + tabGroup->mWindows.AppendElement(aWindow); + return tabGroup.forget(); +} + +void +TabGroup::Leave(nsPIDOMWindowOuter* aWindow) +{ + MOZ_ASSERT(mWindows.Contains(aWindow)); + mWindows.RemoveElement(aWindow); +} + +nsresult +TabGroup::FindItemWithName(const nsAString& aName, + nsIDocShellTreeItem* aRequestor, + nsIDocShellTreeItem* aOriginalRequestor, + nsIDocShellTreeItem** aFoundItem) +{ + NS_ENSURE_ARG_POINTER(aFoundItem); + *aFoundItem = nullptr; + + MOZ_ASSERT(!aName.LowerCaseEqualsLiteral("_blank") && + !aName.LowerCaseEqualsLiteral("_top") && + !aName.LowerCaseEqualsLiteral("_parent") && + !aName.LowerCaseEqualsLiteral("_self")); + + for (nsPIDOMWindowOuter* outerWindow : mWindows) { + // Ignore non-toplevel windows + if (outerWindow->GetScriptableParentOrNull()) { + continue; + } + + nsCOMPtr<nsIDocShellTreeItem> docshell = outerWindow->GetDocShell(); + if (!docshell) { + continue; + } + + nsCOMPtr<nsIDocShellTreeItem> root; + docshell->GetSameTypeRootTreeItem(getter_AddRefs(root)); + MOZ_RELEASE_ASSERT(docshell == root); + if (root && aRequestor != root) { + root->FindItemWithName(aName, this, aOriginalRequestor, aFoundItem); + if (*aFoundItem) { + break; + } + } + } + + return NS_OK; +} + +nsTArray<nsPIDOMWindowOuter*> +TabGroup::GetTopLevelWindows() +{ + nsTArray<nsPIDOMWindowOuter*> array; + + for (nsPIDOMWindowOuter* outerWindow : mWindows) { + if (!outerWindow->GetScriptableParentOrNull()) { + array.AppendElement(outerWindow); + } + } + + return array; +} + +ThrottledEventQueue* +TabGroup::GetThrottledEventQueue() const +{ + return mThrottledEventQueue; +} + +NS_IMPL_ISUPPORTS(TabGroup, nsISupports) + +TabGroup::HashEntry::HashEntry(const nsACString* aKey) + : nsCStringHashKey(aKey), mDocGroup(nullptr) +{} + +} +} |