void
mozilla::dom::TraceBlackJS(JSTracer* aTrc, uint32_t aGCNumber, bool aIsShutdownGC)
{
#ifdef MOZ_XUL
  // Mark the scripts held in the XULPrototypeCache. This is required to keep
  // the JS script in the cache live across GC.
  nsXULPrototypeCache* cache = nsXULPrototypeCache::MaybeGetInstance();
  if (cache) {
    if (aIsShutdownGC) {
      cache->FlushScripts();
    } else {
      cache->MarkInGC(aTrc);
    }
  }
#endif

  if (!nsCCUncollectableMarker::sGeneration) {
    return;
  }

  if (nsFrameMessageManager::GetChildProcessManager()) {
    nsIContentProcessMessageManager* pg = ProcessGlobal::Get();
    if (pg) {
      mozilla::TraceScriptHolder(pg, aTrc);
    }
  }

  // Mark globals of active windows black.
  nsGlobalWindow::WindowByIdTable* windowsById =
    nsGlobalWindow::GetWindowsTable();
  if (windowsById) {
    for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
      nsGlobalWindow* window = iter.Data();
      if (window->GetDocShell() && window->IsOuterWindow()) {
        window->TraceGlobalJSObject(aTrc);
        EventListenerManager* elm = window->GetExistingListenerManager();
        if (elm) {
          elm->TraceListeners(aTrc);
        }

        if (window->IsRootOuterWindow()) {
          // In child process trace all the TabChildGlobals.
          // Since there is one root outer window per TabChildGlobal, we need
          // to look for only those windows, not all.
          nsIDocShell* ds = window->GetDocShell();
          if (ds) {
            nsCOMPtr<nsITabChild> tabChild = ds->GetTabChild();
            if (tabChild) {
              nsCOMPtr<nsIContentFrameMessageManager> mm;
              tabChild->GetMessageManager(getter_AddRefs(mm));
              nsCOMPtr<EventTarget> et = do_QueryInterface(mm);
              if (et) {
                nsCOMPtr<nsISupports> tabChildAsSupports =
                  do_QueryInterface(tabChild);
                mozilla::TraceScriptHolder(tabChildAsSupports, aTrc);
                EventListenerManager* elm = et->GetExistingListenerManager();
                if (elm) {
                  elm->TraceListeners(aTrc);
                }
                // As of now there isn't an easy way to trace message listeners.
              }
            }
          }
        }

#ifdef MOZ_XUL
        nsIDocument* doc = window->GetExtantDoc();
        if (doc && doc->IsXULDocument()) {
          XULDocument* xulDoc = static_cast<XULDocument*>(doc);
          xulDoc->TraceProtos(aTrc, aGCNumber);
        }
#endif
      }
    }
  }
}
Ejemplo n.º 2
0
EventHandlerNonNull*
EventTarget::GetEventHandler(nsIAtom* aType, const nsAString& aTypeString)
{
  EventListenerManager* elm = GetExistingListenerManager();
  return elm ? elm->GetEventHandler(aType, aTypeString) : nullptr;
}
Ejemplo n.º 3
0
bool
EventTarget::HasApzAwareListeners() const
{
  EventListenerManager* elm = GetExistingListenerManager();
  return elm && elm->HasApzAwareListeners();
}
Ejemplo n.º 4
0
OnErrorEventHandlerNonNull* WorkerGlobalScope::GetOnerror() {
  mWorkerPrivate->AssertIsOnWorkerThread();

  EventListenerManager* elm = GetExistingListenerManager();
  return elm ? elm->GetOnErrorEventHandler() : nullptr;
}
Ejemplo n.º 5
0
/* static */
nsresult
nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
                           nsNodeInfoManager *aNewNodeInfoManager,
                           JS::Handle<JSObject*> aReparentScope,
                           nsCOMArray<nsINode> &aNodesWithProperties,
                           nsINode *aParent, nsINode **aResult)
{
  NS_PRECONDITION((!aClone && aNewNodeInfoManager) || !aReparentScope,
                  "If cloning or not getting a new nodeinfo we shouldn't "
                  "rewrap");
  NS_PRECONDITION(!aParent || aNode->IsNodeOfType(nsINode::eCONTENT),
                  "Can't insert document or attribute nodes into a parent");

  *aResult = nullptr;

  // First deal with aNode and walk its attributes (and their children). Then,
  // if aDeep is true, deal with aNode's children (and recurse into their
  // attributes and children).

  nsAutoScriptBlocker scriptBlocker;
  AutoJSContext cx;
  nsresult rv;

  nsNodeInfoManager *nodeInfoManager = aNewNodeInfoManager;

  // aNode.
  NodeInfo *nodeInfo = aNode->mNodeInfo;
  RefPtr<NodeInfo> newNodeInfo;
  if (nodeInfoManager) {

    // Don't allow importing/adopting nodes from non-privileged "scriptable"
    // documents to "non-scriptable" documents.
    nsIDocument* newDoc = nodeInfoManager->GetDocument();
    NS_ENSURE_STATE(newDoc);
    bool hasHadScriptHandlingObject = false;
    if (!newDoc->GetScriptHandlingObject(hasHadScriptHandlingObject) &&
        !hasHadScriptHandlingObject) {
      nsIDocument* currentDoc = aNode->OwnerDoc();
      NS_ENSURE_STATE((nsContentUtils::IsChromeDoc(currentDoc) ||
                       (!currentDoc->GetScriptHandlingObject(hasHadScriptHandlingObject) &&
                        !hasHadScriptHandlingObject)));
    }

    newNodeInfo = nodeInfoManager->GetNodeInfo(nodeInfo->NameAtom(),
                                               nodeInfo->GetPrefixAtom(),
                                               nodeInfo->NamespaceID(),
                                               nodeInfo->NodeType(),
                                               nodeInfo->GetExtraName());

    nodeInfo = newNodeInfo;
  }

  Element *elem = aNode->IsElement() ? aNode->AsElement() : nullptr;

  nsCOMPtr<nsINode> clone;
  if (aClone) {
    rv = aNode->Clone(nodeInfo, getter_AddRefs(clone));
    NS_ENSURE_SUCCESS(rv, rv);

    if (clone->IsElement()) {
      // The cloned node may be a custom element that may require
      // enqueing created callback and prototype swizzling.
      Element* elem = clone->AsElement();
      if (nsContentUtils::IsCustomElementName(nodeInfo->NameAtom())) {
        elem->OwnerDoc()->SetupCustomElement(elem, nodeInfo->NamespaceID());
      } else {
        // Check if node may be custom element by type extension.
        // ex. <button is="x-button">
        nsAutoString extension;
        if (elem->GetAttr(kNameSpaceID_None, nsGkAtoms::is, extension) &&
            !extension.IsEmpty()) {
          elem->OwnerDoc()->SetupCustomElement(elem, nodeInfo->NamespaceID(),
                                               &extension);
        }
      }
    }

    if (aParent) {
      // If we're cloning we need to insert the cloned children into the cloned
      // parent.
      rv = aParent->AppendChildTo(static_cast<nsIContent*>(clone.get()),
                                  false);
      NS_ENSURE_SUCCESS(rv, rv);
    }
    else if (aDeep && clone->IsNodeOfType(nsINode::eDOCUMENT)) {
      // After cloning the document itself, we want to clone the children into
      // the cloned document (somewhat like cloning and importing them into the
      // cloned document).
      nodeInfoManager = clone->mNodeInfo->NodeInfoManager();
    }
  }
  else if (nodeInfoManager) {
    nsIDocument* oldDoc = aNode->OwnerDoc();
    bool wasRegistered = false;
    if (aNode->IsElement()) {
      Element* element = aNode->AsElement();
      oldDoc->ClearBoxObjectFor(element);
      wasRegistered = oldDoc->UnregisterActivityObserver(element);
    }

    aNode->mNodeInfo.swap(newNodeInfo);
    if (elem) {
      elem->NodeInfoChanged(newNodeInfo);
    }

    nsIDocument* newDoc = aNode->OwnerDoc();
    if (newDoc) {
      // XXX what if oldDoc is null, we don't know if this should be
      // registered or not! Can that really happen?
      if (wasRegistered) {
        newDoc->RegisterActivityObserver(aNode->AsElement());
      }

      if (nsPIDOMWindowInner* window = newDoc->GetInnerWindow()) {
        EventListenerManager* elm = aNode->GetExistingListenerManager();
        if (elm) {
          window->SetMutationListeners(elm->MutationListenerBits());
          if (elm->MayHavePaintEventListener()) {
            window->SetHasPaintEventListeners();
          }
          if (elm->MayHaveTouchEventListener()) {
            window->SetHasTouchEventListeners();
          }
          if (elm->MayHaveMouseEnterLeaveEventListener()) {
            window->SetHasMouseEnterLeaveEventListeners();
          }
          if (elm->MayHavePointerEnterLeaveEventListener()) {
            window->SetHasPointerEnterLeaveEventListeners();
          }
        }
      }
    }

    if (wasRegistered && oldDoc != newDoc) {
      nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
      if (domMediaElem) {
        HTMLMediaElement* mediaElem = static_cast<HTMLMediaElement*>(aNode);
        mediaElem->NotifyOwnerDocumentActivityChanged();
      }
      nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aNode));
      if (objectLoadingContent) {
        nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
        olc->NotifyOwnerDocumentActivityChanged();
      }
    }

    if (oldDoc != newDoc && oldDoc->MayHaveDOMMutationObservers()) {
      newDoc->SetMayHaveDOMMutationObservers();
    }

    if (oldDoc != newDoc && oldDoc->MayHaveAnimationObservers()) {
      newDoc->SetMayHaveAnimationObservers();
    }

    if (elem) {
      elem->RecompileScriptEventListeners();
    }

    if (aReparentScope) {
      JS::Rooted<JSObject*> wrapper(cx);
      if ((wrapper = aNode->GetWrapper())) {
        MOZ_ASSERT(IsDOMObject(wrapper));
        JSAutoCompartment ac(cx, wrapper);
        rv = ReparentWrapper(cx, wrapper);
        if (NS_FAILED(rv)) {
          aNode->mNodeInfo.swap(nodeInfo);

          return rv;
        }
      }
    }
  }

  if (aDeep && (!aClone || !aNode->IsNodeOfType(nsINode::eATTRIBUTE))) {
    // aNode's children.
    for (nsIContent* cloneChild = aNode->GetFirstChild();
         cloneChild;
         cloneChild = cloneChild->GetNextSibling()) {
      nsCOMPtr<nsINode> child;
      rv = CloneAndAdopt(cloneChild, aClone, true, nodeInfoManager,
                         aReparentScope, aNodesWithProperties, clone,
                         getter_AddRefs(child));
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }

  // Cloning template element.
  if (aDeep && aClone && IsTemplateElement(aNode)) {
    DocumentFragment* origContent =
      static_cast<HTMLTemplateElement*>(aNode)->Content();
    DocumentFragment* cloneContent =
      static_cast<HTMLTemplateElement*>(clone.get())->Content();

    // Clone the children into the clone's template content owner
    // document's nodeinfo manager.
    nsNodeInfoManager* ownerNodeInfoManager =
      cloneContent->mNodeInfo->NodeInfoManager();

    for (nsIContent* cloneChild = origContent->GetFirstChild();
         cloneChild;
         cloneChild = cloneChild->GetNextSibling()) {
      nsCOMPtr<nsINode> child;
      rv = CloneAndAdopt(cloneChild, aClone, aDeep, ownerNodeInfoManager,
                         aReparentScope, aNodesWithProperties, cloneContent,
                         getter_AddRefs(child));
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }

  // XXX setting document on some nodes not in a document so XBL will bind
  // and chrome won't break. Make XBL bind to document-less nodes!
  // XXXbz Once this is fixed, fix up the asserts in all implementations of
  // BindToTree to assert what they would like to assert, and fix the
  // ChangeDocumentFor() call in nsXULElement::BindToTree as well.  Also,
  // remove the UnbindFromTree call in ~nsXULElement, and add back in the
  // precondition in nsXULElement::UnbindFromTree and remove the line in
  // nsXULElement.h that makes nsNodeUtils a friend of nsXULElement.
  // Note: Make sure to do this witchery _after_ we've done any deep
  // cloning, so kids of the new node aren't confused about whether they're
  // in a document.
#ifdef MOZ_XUL
  if (aClone && !aParent && aNode->IsXULElement()) {
    if (!aNode->OwnerDoc()->IsLoadedAsInteractiveData()) {
      clone->SetFlags(NODE_FORCE_XBL_BINDINGS);
    }
  }
#endif

  if (aNode->HasProperties()) {
    bool ok = aNodesWithProperties.AppendObject(aNode);
    if (aClone) {
      ok = ok && aNodesWithProperties.AppendObject(clone);
    }

    NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
  }

  clone.forget(aResult);

  return NS_OK;
}
void mozilla::dom::TraceBlackJS(JSTracer* aTrc, bool aIsShutdownGC) {
#ifdef MOZ_XUL
  // Mark the scripts held in the XULPrototypeCache. This is required to keep
  // the JS script in the cache live across GC.
  nsXULPrototypeCache* cache = nsXULPrototypeCache::MaybeGetInstance();
  if (cache) {
    if (aIsShutdownGC) {
      cache->FlushScripts();
    } else {
      cache->MarkInGC(aTrc);
    }
  }
#endif

  if (!nsCCUncollectableMarker::sGeneration) {
    return;
  }

  if (ContentProcessMessageManager::WasCreated() &&
      nsFrameMessageManager::GetChildProcessManager()) {
    auto* pg = ContentProcessMessageManager::Get();
    if (pg) {
      mozilla::TraceScriptHolder(ToSupports(pg), aTrc);
    }
  }

  // Mark globals of active windows black.
  nsGlobalWindowOuter::OuterWindowByIdTable* windowsById =
      nsGlobalWindowOuter::GetWindowsTable();
  if (windowsById) {
    for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
      nsGlobalWindowOuter* window = iter.Data();
      if (!window->IsCleanedUp()) {
        nsGlobalWindowInner* inner = nullptr;
        for (PRCList* win = PR_LIST_HEAD(window); win != window;
             win = PR_NEXT_LINK(inner)) {
          inner = static_cast<nsGlobalWindowInner*>(win);
          if (inner->IsCurrentInnerWindow() ||
              (inner->GetExtantDoc() &&
               inner->GetExtantDoc()->GetBFCacheEntry())) {
            inner->TraceGlobalJSObject(aTrc);
            EventListenerManager* elm = inner->GetExistingListenerManager();
            if (elm) {
              elm->TraceListeners(aTrc);
            }
          }
        }

        if (window->IsRootOuterWindow()) {
          // In child process trace all the TabChildMessageManagers.
          // Since there is one root outer window per TabChildMessageManager, we
          // need to look for only those windows, not all.
          nsIDocShell* ds = window->GetDocShell();
          if (ds) {
            nsCOMPtr<nsITabChild> tabChild = ds->GetTabChild();
            if (tabChild) {
              RefPtr<ContentFrameMessageManager> mm;
              tabChild->GetMessageManager(getter_AddRefs(mm));
              if (mm) {
                nsCOMPtr<nsISupports> tabChildAsSupports =
                    do_QueryInterface(tabChild);
                mozilla::TraceScriptHolder(tabChildAsSupports, aTrc);
                EventListenerManager* elm = mm->GetExistingListenerManager();
                if (elm) {
                  elm->TraceListeners(aTrc);
                }
                // As of now there isn't an easy way to trace message listeners.
              }
            }
          }
        }

#ifdef MOZ_XUL
        Document* doc = window->GetExtantDoc();
        if (doc) {
          doc->TraceProtos(aTrc);
        }
#endif
      }
    }
  }
}
Ejemplo n.º 7
0
void
nsEditorEventListener::UninstallFromEditor()
{
  nsCOMPtr<EventTarget> piTarget = mEditor->GetDOMEventTarget();
  if (!piTarget) {
    return;
  }

  EventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
  if (!elmP) {
    return;
  }

#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("keydown"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("keyup"),
                                  TrustedEventsAtSystemGroupBubble());
#endif
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("keypress"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("dragenter"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("dragover"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("dragexit"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("drop"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("mousedown"),
                                  TrustedEventsAtCapture());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("mouseup"),
                                  TrustedEventsAtCapture());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("click"),
                                  TrustedEventsAtCapture());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("blur"),
                                  TrustedEventsAtCapture());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("focus"),
                                  TrustedEventsAtCapture());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("text"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("compositionstart"),
                                  TrustedEventsAtSystemGroupBubble());
  elmP->RemoveEventListenerByType(this,
                                  NS_LITERAL_STRING("compositionend"),
                                  TrustedEventsAtSystemGroupBubble());
}
Ejemplo n.º 8
0
nsresult
nsEditorEventListener::InstallToEditor()
{
  NS_PRECONDITION(mEditor, "The caller must set mEditor");

  nsCOMPtr<EventTarget> piTarget = mEditor->GetDOMEventTarget();
  NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);

  // register the event listeners with the listener manager
  EventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
  NS_ENSURE_STATE(elmP);

#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("keydown"),
                               TrustedEventsAtSystemGroupBubble());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("keyup"),
                               TrustedEventsAtSystemGroupBubble());
#endif
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("keypress"),
                               TrustedEventsAtSystemGroupBubble());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("dragenter"),
                               TrustedEventsAtSystemGroupBubble());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("dragover"),
                               TrustedEventsAtSystemGroupBubble());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("dragexit"),
                               TrustedEventsAtSystemGroupBubble());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("drop"),
                               TrustedEventsAtSystemGroupBubble());
  // XXX We should add the mouse event listeners as system event group.
  //     E.g., web applications cannot prevent middle mouse paste by
  //     preventDefault() of click event at bubble phase.
  //     However, if we do so, all click handlers in any frames and frontend
  //     code need to check if it's editable.  It makes easier create new bugs.
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("mousedown"),
                               TrustedEventsAtCapture());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("mouseup"),
                               TrustedEventsAtCapture());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("click"),
                               TrustedEventsAtCapture());
// Focus event doesn't bubble so adding the listener to capturing phase.
// Make sure this works after bug 235441 gets fixed.
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("blur"),
                               TrustedEventsAtCapture());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("focus"),
                               TrustedEventsAtCapture());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("text"),
                               TrustedEventsAtSystemGroupBubble());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("compositionstart"),
                               TrustedEventsAtSystemGroupBubble());
  elmP->AddEventListenerByType(this,
                               NS_LITERAL_STRING("compositionend"),
                               TrustedEventsAtSystemGroupBubble());

  return NS_OK;
}