nsresult nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMArray<nsIFile> &aDirs) { nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1"); NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE); nsresult rv = regKey->Open(aKey, NS_LITERAL_STRING("Software\\MozillaPlugins"), nsIWindowsRegKey::ACCESS_READ); if (NS_FAILED(rv)) { return rv; } uint32_t childCount = 0; regKey->GetChildCount(&childCount); for (uint32_t index = 0; index < childCount; ++index) { nsAutoString childName; rv = regKey->GetChildName(index, childName); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIWindowsRegKey> childKey; rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE, getter_AddRefs(childKey)); if (NS_SUCCEEDED(rv) && childKey) { nsAutoString path; rv = childKey->ReadStringValue(NS_LITERAL_STRING("Path"), path); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIFile> localFile; if (NS_SUCCEEDED(NS_NewLocalFile(path, true, getter_AddRefs(localFile))) && localFile) { // Some vendors use a path directly to the DLL so chop off // the filename bool isDir = false; if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) { nsCOMPtr<nsIFile> temp; localFile->GetParent(getter_AddRefs(temp)); if (temp) localFile = temp; } // Now we check to make sure it's actually on disk and // To see if we already have this directory in the array bool isFileThere = false; bool isDupEntry = false; if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) { int32_t c = aDirs.Count(); for (int32_t i = 0; i < c; i++) { nsIFile *dup = static_cast<nsIFile*>(aDirs[i]); if (dup && NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) && isDupEntry) { break; } } if (!isDupEntry) { aDirs.AppendObject(localFile); } } } } } } } return NS_OK; }
static void AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array) { nsCOMPtr<nsIFile> searchPlugins; nsresult rv = aDirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(searchPlugins)); if (NS_FAILED(rv)) return; searchPlugins->AppendNative(NS_LITERAL_CSTRING("distribution")); searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins")); PRBool exists; rv = searchPlugins->Exists(&exists); if (NS_FAILED(rv) || !exists) return; nsCOMPtr<nsIFile> commonPlugins; rv = searchPlugins->Clone(getter_AddRefs(commonPlugins)); if (NS_SUCCEEDED(rv)) { commonPlugins->AppendNative(NS_LITERAL_CSTRING("common")); rv = commonPlugins->Exists(&exists); if (NS_SUCCEEDED(rv) && exists) array.AppendObject(commonPlugins); } nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefs) { nsCOMPtr<nsIFile> localePlugins; rv = searchPlugins->Clone(getter_AddRefs(localePlugins)); if (NS_FAILED(rv)) return; localePlugins->AppendNative(NS_LITERAL_CSTRING("locale")); nsCString locale; rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale)); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIFile> curLocalePlugins; rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins)); if (NS_SUCCEEDED(rv)) { curLocalePlugins->AppendNative(locale); rv = curLocalePlugins->Exists(&exists); if (NS_SUCCEEDED(rv) && exists) { array.AppendObject(curLocalePlugins); return; // all done } } } // we didn't append the locale dir - try the default one nsCString defLocale; rv = prefs->GetCharPref("distribution.searchplugins.defaultLocale", getter_Copies(defLocale)); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIFile> defLocalePlugins; rv = localePlugins->Clone(getter_AddRefs(defLocalePlugins)); if (NS_SUCCEEDED(rv)) { defLocalePlugins->AppendNative(defLocale); rv = defLocalePlugins->Exists(&exists); if (NS_SUCCEEDED(rv) && exists) array.AppendObject(defLocalePlugins); } } } }
/* 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). AutoJSContext cx; nsresult rv; nsNodeInfoManager *nodeInfoManager = aNewNodeInfoManager; // aNode. nsINodeInfo *nodeInfo = aNode->mNodeInfo; nsCOMPtr<nsINodeInfo> 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 (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->UnregisterFreezableElement(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->RegisterFreezableElement(aNode->AsElement()); } nsPIDOMWindow* window = newDoc->GetInnerWindow(); if (window) { nsEventListenerManager* elm = aNode->GetExistingListenerManager(); if (elm) { window->SetMutationListeners(elm->MutationListenerBits()); if (elm->MayHavePaintEventListener()) { window->SetHasPaintEventListeners(); } if (elm->MayHaveAudioAvailableEventListener()) { window->SetHasAudioAvailableEventListeners(); } if (elm->MayHaveTouchEventListener()) { window->SetHasTouchEventListeners(); } if (elm->MayHaveMouseEnterLeaveEventListener()) { window->SetHasMouseEnterLeaveEventListeners(); } } } } 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 (elem) { elem->RecompileScriptEventListeners(); } if (aReparentScope) { JS::Rooted<JSObject*> wrapper(cx); if ((wrapper = aNode->GetWrapper())) { if (IsDOMObject(wrapper)) { rv = ReparentWrapper(cx, wrapper); } else { nsIXPConnect *xpc = nsContentUtils::XPConnect(); if (xpc) { rv = xpc->ReparentWrappedNativeIfFound(cx, wrapper, aReparentScope, aNode); } else { rv = NS_ERROR_FAILURE; } } if (NS_FAILED(rv)) { aNode->mNodeInfo.swap(nodeInfo); return rv; } } } } // XXX If there are any attribute nodes on this element with UserDataHandlers // we should technically adopt/clone/import such attribute nodes and notify // those handlers. However we currently don't have code to do so without // also notifying when it's not safe so we're not doing that at this time. 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->IsElement() && aNode->AsElement()->IsXUL()) { 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; }
static void do_dladm(nsCOMArray<nsWifiAccessPoint> &accessPoints) { GError *err = NULL; char *sout = NULL; char *serr = NULL; int exit_status = 0; char * dladm_args[] = { "/usr/bin/pfexec", "/usr/sbin/dladm", "scan-wifi", "-p", "-o", "BSSID,ESSID,STRENGTH" }; gboolean rv = g_spawn_sync("/", dladm_args, NULL, (GSpawnFlags)0, NULL, NULL, &sout, &serr, &exit_status, &err); if (rv && !exit_status) { char wlan[DLADM_SECTIONS][DLADM_STRSIZE+1]; uint32_t section = 0; uint32_t sout_scan = 0; uint32_t wlan_put = 0; bool escape = false; nsWifiAccessPoint* ap; char sout_char; do { sout_char = sout[sout_scan++]; if (escape) { escape = false; if (sout_char != '\0') { wlan[section][wlan_put++] = sout_char; continue; } } if (sout_char =='\\') { escape = true; continue; } if (sout_char == ':') { wlan[section][wlan_put] = '\0'; section++; wlan_put = 0; continue; } if ((sout_char == '\0') || (sout_char == '\n')) { wlan[section][wlan_put] = '\0'; if (section == DLADM_SECTIONS - 1) { ap = do_parse_str(wlan[0], wlan[1], wlan[2]); if (ap) { accessPoints.AppendObject(ap); } } section = 0; wlan_put = 0; continue; } wlan[section][wlan_put++] = sout_char; } while ((wlan_put <= DLADM_STRSIZE) && (section < DLADM_SECTIONS) && (sout_char != '\0')); } g_free(sout); g_free(serr); }
nsresult WinWifiScanner::GetAccessPointsFromWLAN(nsCOMArray<nsWifiAccessPoint> &accessPoints) { accessPoints.Clear(); // NOTE: We do not try to load the WLAN library if we previously failed // to load it. See the note in WinWifiScanner constructor if (!mWlanLibrary) { return NS_ERROR_NOT_AVAILABLE; } // Get the list of interfaces. WlanEnumInterfaces allocates interface_list. WLAN_INTERFACE_INFO_LIST *interface_list = nullptr; if (ERROR_SUCCESS != (*mWlanLibrary->GetWlanEnumInterfacesPtr())(mWlanLibrary->GetWLANHandle(), nullptr, &interface_list)) { return NS_ERROR_FAILURE; } // This ensures we call WlanFreeMemory on interface_list ScopedWLANObject scopedInterfaceList(mWlanLibrary, interface_list); if (!interface_list->dwNumberOfItems) { return NS_OK; } InterfaceScanCallbackData cbData(interface_list->dwNumberOfItems); DWORD wlanNotifySource; if (ERROR_SUCCESS != (*mWlanLibrary->GetWlanRegisterNotificationPtr())( mWlanLibrary->GetWLANHandle(), WLAN_NOTIFICATION_SOURCE_ACM, TRUE, (WLAN_NOTIFICATION_CALLBACK)OnScanComplete, &cbData, NULL, &wlanNotifySource)) { return NS_ERROR_FAILURE; } // Go through the list of interfaces and call `WlanScan` on each for (unsigned int i = 0; i < interface_list->dwNumberOfItems; ++i) { if (ERROR_SUCCESS != (*mWlanLibrary->GetWlanScanPtr())( mWlanLibrary->GetWLANHandle(), &interface_list->InterfaceInfo[i].InterfaceGuid, NULL, NULL, NULL)) { cbData.OnInterfaceScanComplete(); } } // From the MSDN documentation: // "Wireless network drivers that meet Windows logo requirements are // required to complete a WlanScan function request in 4 seconds" cbData.WaitForAllInterfacesToFinishScanning(5000); // Unregister for the notifications. The documentation mentions that, // if a callback is currently running, this will wait for the callback // to complete. (*mWlanLibrary->GetWlanRegisterNotificationPtr())( mWlanLibrary->GetWLANHandle(), WLAN_NOTIFICATION_SOURCE_NONE, TRUE, NULL, NULL, NULL, &wlanNotifySource); // Go through the list of interfaces and get the data for each. for (uint32_t i = 0; i < interface_list->dwNumberOfItems; ++i) { WLAN_BSS_LIST *bss_list; if (ERROR_SUCCESS != (*mWlanLibrary->GetWlanGetNetworkBssListPtr())( mWlanLibrary->GetWLANHandle(), &interface_list->InterfaceInfo[i].InterfaceGuid, nullptr, // Use all SSIDs. DOT11_BSS_TYPE_UNUSED, false, // bSecurityEnabled - unused nullptr, // reserved &bss_list)) { continue; } // This ensures we call WlanFreeMemory on bss_list ScopedWLANObject scopedBssList(mWlanLibrary, bss_list); // Store each discovered access point in our outparam for (int j = 0; j < static_cast<int>(bss_list->dwNumberOfItems); ++j) { nsWifiAccessPoint* ap = new nsWifiAccessPoint(); if (!ap) { continue; } const WLAN_BSS_ENTRY bss_entry = bss_list->wlanBssEntries[j]; ap->setMac(bss_entry.dot11Bssid); ap->setSignal(bss_entry.lRssi); ap->setSSID(reinterpret_cast<char const*>(bss_entry.dot11Ssid.ucSSID), bss_entry.dot11Ssid.uSSIDLength); accessPoints.AppendObject(ap); } } return NS_OK; }
/* static */ nsresult nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep, nsNodeInfoManager *aNewNodeInfoManager, JSContext *aCx, JSObject *aNewScope, nsCOMArray<nsINode> &aNodesWithProperties, nsINode *aParent, nsINode **aResult) { NS_PRECONDITION((!aClone && aNewNodeInfoManager) || !aCx, "If cloning or not getting a new nodeinfo we shouldn't " "rewrap"); NS_PRECONDITION(!aCx || aNewScope, "Must have new scope"); NS_PRECONDITION(!aParent || aNode->IsNodeOfType(nsINode::eCONTENT), "Can't insert document or attribute nodes into a parent"); *aResult = nsnull; // First deal with aNode and walk its attributes (and their children). Then, // if aDeep is PR_TRUE, deal with aNode's children (and recurse into their // attributes and children). nsresult rv; JSObject *wrapper; if (aCx && (wrapper = aNode->GetWrapper())) { rv = xpc_MorphSlimWrapper(aCx, aNode); NS_ENSURE_SUCCESS(rv, rv); } nsNodeInfoManager *nodeInfoManager = aNewNodeInfoManager; // aNode. nsINodeInfo *nodeInfo = aNode->mNodeInfo; nsCOMPtr<nsINodeInfo> 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); PRBool hasHadScriptHandlingObject = PR_FALSE; if (!newDoc->GetScriptHandlingObject(hasHadScriptHandlingObject) && !hasHadScriptHandlingObject) { nsIDocument* currentDoc = aNode->GetOwnerDoc(); NS_ENSURE_STATE(currentDoc && (nsContentUtils::IsChromeDoc(currentDoc) || (!currentDoc->GetScriptHandlingObject(hasHadScriptHandlingObject) && !hasHadScriptHandlingObject))); } newNodeInfo = nodeInfoManager->GetNodeInfo(nodeInfo->NameAtom(), nodeInfo->GetPrefixAtom(), nodeInfo->NamespaceID()); NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY); nodeInfo = newNodeInfo; } nsGenericElement *elem = aNode->IsElement() ? static_cast<nsGenericElement*>(aNode) : nsnull; nsCOMPtr<nsINode> clone; PRBool isDeepDocumentClone = PR_FALSE; if (aClone) { rv = aNode->Clone(nodeInfo, getter_AddRefs(clone)); NS_ENSURE_SUCCESS(rv, rv); 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()), PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); } else if (aDeep && clone->IsNodeOfType(nsINode::eDOCUMENT)) { isDeepDocumentClone = PR_TRUE; // 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->GetOwnerDoc(); PRBool wasRegistered = PR_FALSE; if (oldDoc && aNode->IsElement()) { Element* element = aNode->AsElement(); oldDoc->ClearBoxObjectFor(element); wasRegistered = oldDoc->UnregisterFreezableElement(element); } aNode->mNodeInfo.swap(newNodeInfo); if (elem) { elem->NodeInfoChanged(newNodeInfo); } nsIDocument* newDoc = aNode->GetOwnerDoc(); 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->RegisterFreezableElement(aNode->AsElement()); } nsPIDOMWindow* window = newDoc->GetInnerWindow(); if (window) { nsIEventListenerManager* elm = aNode->GetListenerManager(PR_FALSE); if (elm) { window->SetMutationListeners(elm->MutationListenerBits()); if (elm->MayHavePaintEventListener()) { window->SetHasPaintEventListeners(); } #ifdef MOZ_MEDIA if (elm->MayHaveAudioAvailableEventListener()) { window->SetHasAudioAvailableEventListeners(); } #endif if (elm->MayHaveTouchEventListener()) { window->SetHasTouchEventListeners(); } } } } #ifdef MOZ_MEDIA if (wasRegistered && oldDoc != newDoc) { nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode)); if (domMediaElem) { nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aNode); mediaElem->NotifyOwnerDocumentActivityChanged(); } } #endif // nsImageLoadingContent needs to know when its document changes if (oldDoc != newDoc) { nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aNode)); if (imageContent) imageContent->NotifyOwnerDocumentChanged(oldDoc); } if (elem) { elem->RecompileScriptEventListeners(); } if (aCx && wrapper) { nsIXPConnect *xpc = nsContentUtils::XPConnect(); if (xpc) { JSObject *preservedWrapper = nsnull; // If reparenting moves us to a new compartment, preserving causes // problems. In that case, we release ourselves and re-preserve after // reparenting so we're sure to have the right JS object preserved. // We use a JSObject stack copy of the wrapper to protect it from GC // under ReparentWrappedNativeIfFound. if (aNode->PreservingWrapper()) { preservedWrapper = wrapper; nsContentUtils::ReleaseWrapper(aNode, aNode); } nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper; rv = xpc->ReparentWrappedNativeIfFound(aCx, wrapper, aNewScope, aNode, getter_AddRefs(oldWrapper)); if (preservedWrapper) { nsContentUtils::PreserveWrapper(aNode, aNode); } if (NS_FAILED(rv)) { aNode->mNodeInfo.swap(nodeInfo); return rv; } } } } // XXX If there are any attribute nodes on this element with UserDataHandlers // we should technically adopt/clone/import such attribute nodes and notify // those handlers. However we currently don't have code to do so without // also notifying when it's not safe so we're not doing that at this time. // The DOM spec says to always adopt/clone/import the children of attribute // nodes. // XXX The following block is here because our implementation of attribute // nodes is broken when it comes to inserting children. Instead of cloning // their children we force creation of the only child by calling // GetChildAt(0). We can remove this when // https://bugzilla.mozilla.org/show_bug.cgi?id=56758 is fixed. if (aClone && aNode->IsNodeOfType(nsINode::eATTRIBUTE)) { nsCOMPtr<nsINode> attrChildNode = aNode->GetChildAt(0); // We only need to do this if the child node has properties (because we // might need to call a userdata handler). if (attrChildNode && attrChildNode->HasProperties()) { nsCOMPtr<nsINode> clonedAttrChildNode = clone->GetChildAt(0); if (clonedAttrChildNode) { PRBool ok = aNodesWithProperties.AppendObject(attrChildNode) && aNodesWithProperties.AppendObject(clonedAttrChildNode); NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); } } } // XXX End of workaround for broken attribute nodes. else if (aDeep || aNode->IsNodeOfType(nsINode::eATTRIBUTE)) { // aNode's children. PRUint32 i, length = aNode->GetChildCount(); for (i = 0; i < length; ++i) { nsCOMPtr<nsINode> child; rv = CloneAndAdopt(aNode->GetChildAt(i), aClone, PR_TRUE, nodeInfoManager, aCx, aNewScope, aNodesWithProperties, clone, 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->IsElement() && aNode->AsElement()->IsXUL()) { nsXULElement *xulElem = static_cast<nsXULElement*>(elem); if (!xulElem->mPrototype || xulElem->IsInDoc()) { clone->SetFlags(NODE_FORCE_XBL_BINDINGS); } } #endif if (aNode->HasProperties()) { PRBool 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; }