tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ChromeObserver.cpp (4424B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #include "ChromeObserver.h"
      8 
      9 #include "mozilla/dom/Document.h"
     10 #include "mozilla/dom/DocumentInlines.h"
     11 #include "mozilla/dom/Element.h"
     12 #include "nsContentUtils.h"
     13 #include "nsIBaseWindow.h"
     14 #include "nsIFrame.h"
     15 #include "nsIMutationObserver.h"
     16 #include "nsIWidget.h"
     17 #include "nsPresContext.h"
     18 #include "nsXULElement.h"
     19 
     20 namespace mozilla::dom {
     21 
     22 NS_IMPL_ISUPPORTS(ChromeObserver, nsIMutationObserver)
     23 
     24 ChromeObserver::ChromeObserver(Document* aDocument)
     25    : nsStubMutationObserver(), mDocument(aDocument) {}
     26 
     27 ChromeObserver::~ChromeObserver() = default;
     28 
     29 void ChromeObserver::Init() {
     30  mDocument->AddMutationObserver(this);
     31  Element* rootElement = mDocument->GetRootElement();
     32  if (!rootElement) {
     33    return;
     34  }
     35  nsAutoScriptBlocker scriptBlocker;
     36  uint32_t attributeCount = rootElement->GetAttrCount();
     37  for (uint32_t i = 0; i < attributeCount; i++) {
     38    BorrowedAttrInfo info = rootElement->GetAttrInfoAt(i);
     39    const nsAttrName* name = info.mName;
     40    if (name->LocalName() == nsGkAtoms::customtitlebar) {
     41      // Some linux windows managers have an issue when the customtitlebar is
     42      // applied while the browser is loading (bug 1598848). For now, skip
     43      // applying this attribute when initializing.
     44      continue;
     45    }
     46    AttributeChanged(rootElement, name->NamespaceID(), name->LocalName(),
     47                     AttrModType::Addition, nullptr);
     48  }
     49 }
     50 
     51 nsIWidget* ChromeObserver::GetWindowWidget() {
     52  // only top level chrome documents can set the titlebar color
     53  if (mDocument && mDocument->IsRootDisplayDocument()) {
     54    nsCOMPtr<nsISupports> container = mDocument->GetContainer();
     55    if (nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container)) {
     56      nsCOMPtr<nsIWidget> mainWidget = baseWindow->GetMainWidget();
     57      return mainWidget;
     58    }
     59  }
     60  return nullptr;
     61 }
     62 
     63 void ChromeObserver::SetHideTitlebarSeparator(bool aState) {
     64  nsIWidget* mainWidget = GetWindowWidget();
     65  if (mainWidget) {
     66    // We can do this synchronously because SetHideTitlebarSeparator doesn't
     67    // have any synchronous effects apart from a harmless invalidation.
     68    mainWidget->SetHideTitlebarSeparator(aState);
     69  }
     70 }
     71 
     72 void ChromeObserver::AttributeChanged(dom::Element* aElement,
     73                                      int32_t aNamespaceID, nsAtom* aName,
     74                                      AttrModType aModType,
     75                                      const nsAttrValue* aOldValue) {
     76  // We only care about changes to the root element.
     77  if (!mDocument || aElement != mDocument->GetRootElement()) {
     78    return;
     79  }
     80 
     81  if (IsAdditionOrRemoval(aModType)) {
     82    const bool added = aModType == AttrModType::Addition;
     83    if (aName == nsGkAtoms::hidechrome) {
     84      HideWindowChrome(added);
     85    } else if (aName == nsGkAtoms::customtitlebar) {
     86      SetCustomTitlebar(added);
     87    } else if (aName == nsGkAtoms::hidetitlebarseparator) {
     88      SetHideTitlebarSeparator(added);
     89    } else if (aName == nsGkAtoms::windowsmica) {
     90      SetMica(added);
     91    }
     92  }
     93  if (aName == nsGkAtoms::localedir) {
     94    // if the localedir changed on the root element, reset the document
     95    // direction
     96    mDocument->ResetDocumentDirection();
     97  }
     98  if (aName == nsGkAtoms::title && aModType != AttrModType::Removal) {
     99    mDocument->NotifyPossibleTitleChange(false);
    100  }
    101 }
    102 
    103 void ChromeObserver::NodeWillBeDestroyed(nsINode* aNode) {
    104  mDocument = nullptr;
    105 }
    106 
    107 void ChromeObserver::SetMica(bool aEnable) {
    108  if (nsIWidget* mainWidget = GetWindowWidget()) {
    109    mainWidget->SetMicaBackdrop(aEnable);
    110  }
    111 }
    112 
    113 void ChromeObserver::SetCustomTitlebar(bool aCustomTitlebar) {
    114  if (nsIWidget* mainWidget = GetWindowWidget()) {
    115    // SetCustomTitlebar can dispatch native events, hence doing it off a
    116    // script runner
    117    nsContentUtils::AddScriptRunner(NewRunnableMethod<bool>(
    118        "SetCustomTitlebar", mainWidget, &nsIWidget::SetCustomTitlebar,
    119        aCustomTitlebar));
    120  }
    121 }
    122 
    123 void ChromeObserver::HideWindowChrome(bool aShouldHide) {
    124  if (nsCOMPtr<nsIWidget> mainWidget = GetWindowWidget()) {
    125    mainWidget->HideWindowChrome(aShouldHide);
    126  }
    127 }
    128 
    129 }  // namespace mozilla::dom