📄 legacywebarchive.cpp
字号:
return false; } return extract(plist.get());}bool LegacyWebArchive::extract(CFDictionaryRef dictionary){ ASSERT(dictionary); if (!dictionary) { LOG(Archives, "LegacyWebArchive - Null root CFDictionary, aborting invalid WebArchive"); return false; } CFDictionaryRef mainResourceDict = static_cast<CFDictionaryRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveMainResourceKey)); if (!mainResourceDict) { LOG(Archives, "LegacyWebArchive - No main resource in archive, aborting invalid WebArchive"); return false; } if (CFGetTypeID(mainResourceDict) != CFDictionaryGetTypeID()) { LOG(Archives, "LegacyWebArchive - Main resource is not the expected CFDictionary, aborting invalid WebArchive"); return false; } setMainResource(createResource(mainResourceDict)); if (!mainResource()) { LOG(Archives, "LegacyWebArchive - Failed to parse main resource from CFDictionary or main resource does not exist, aborting invalid WebArchive"); return false; } CFArrayRef subresourceArray = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveSubresourcesKey)); if (subresourceArray && CFGetTypeID(subresourceArray) != CFArrayGetTypeID()) { LOG(Archives, "LegacyWebArchive - Subresources is not the expected Array, aborting invalid WebArchive"); return false; } if (subresourceArray) { CFIndex count = CFArrayGetCount(subresourceArray); for (CFIndex i = 0; i < count; ++i) { CFDictionaryRef subresourceDict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(subresourceArray, i)); if (CFGetTypeID(subresourceDict) != CFDictionaryGetTypeID()) { LOG(Archives, "LegacyWebArchive - Subresource is not expected CFDictionary, aborting invalid WebArchive"); return false; } addSubresource(createResource(subresourceDict)); } } CFArrayRef subframeArray = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, LegacyWebArchiveSubframeArchivesKey)); if (subframeArray && CFGetTypeID(subframeArray) != CFArrayGetTypeID()) { LOG(Archives, "LegacyWebArchive - Subframe archives is not the expected Array, aborting invalid WebArchive"); return false; } if (subframeArray) { CFIndex count = CFArrayGetCount(subframeArray); for (CFIndex i = 0; i < count; ++i) { CFDictionaryRef subframeDict = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(subframeArray, i)); if (CFGetTypeID(subframeDict) != CFDictionaryGetTypeID()) { LOG(Archives, "LegacyWebArchive - Subframe array is not expected CFDictionary, aborting invalid WebArchive"); return false; } RefPtr<LegacyWebArchive> subframeArchive = create(); if (subframeArchive->extract(subframeDict)) addSubframeArchive(subframeArchive.release()); else LOG(Archives, "LegacyWebArchive - Invalid subframe archive skipped"); } } return true;}RetainPtr<CFDataRef> LegacyWebArchive::rawDataRepresentation(){ RetainPtr<CFDictionaryRef> propertyList = createPropertyListRep(this); if (!propertyList) { LOG(Archives, "LegacyWebArchive - Failed to create property list for archive, returning no data"); return 0; } RetainPtr<CFWriteStreamRef> stream(AdoptCF, CFWriteStreamCreateWithAllocatedBuffers(0, 0)); CFWriteStreamOpen(stream.get()); CFPropertyListWriteToStream(propertyList.get(), stream.get(), kCFPropertyListBinaryFormat_v1_0, 0); RetainPtr<CFDataRef> plistData(AdoptCF, static_cast<CFDataRef>(CFWriteStreamCopyProperty(stream.get(), kCFStreamPropertyDataWritten))); CFWriteStreamClose(stream.get()); if (!plistData) { LOG(Archives, "LegacyWebArchive - Failed to convert property list into raw data, returning no data"); return 0; } return plistData;}#if !PLATFORM(MAC)// FIXME: Is it possible to parse in a Cocoa-style resource response manually, // without NSKeyed(Un)Archiver, manipulating plists directly?// If so, the code that does it will go here. // In the meantime, Mac will continue to NSKeyed(Un)Archive the response as it always hasResourceResponse createResourceResponseFromMacArchivedData(CFDataRef responseData){ return ResourceResponse();}RetainPtr<CFDataRef> propertyListDataFromResourceResponse(const ResourceResponse& response){ // FIXME: Write out the "new" format described in ::createResourceResponseFromPropertyListData() up above return 0;}#endifPassRefPtr<LegacyWebArchive> LegacyWebArchive::create(Node* node){ ASSERT(node); if (!node) return create(); Document* document = node->document(); Frame* frame = document ? document->frame() : 0; if (!frame) return create(); Vector<Node*> nodeList; String markupString = createMarkup(node, IncludeNode, &nodeList); Node::NodeType nodeType = node->nodeType(); if (nodeType != Node::DOCUMENT_NODE && nodeType != Node::DOCUMENT_TYPE_NODE) markupString = frame->documentTypeString() + markupString; return create(markupString, frame, nodeList);}PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(Frame* frame){ ASSERT(frame); DocumentLoader* documentLoader = frame->loader()->documentLoader(); if (!documentLoader) return 0; Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; unsigned children = frame->tree()->childCount(); for (unsigned i = 0; i < children; ++i) { RefPtr<LegacyWebArchive> childFrameArchive = create(frame->tree()->child(i)); if (childFrameArchive) subframeArchives.append(childFrameArchive.release()); } Vector<PassRefPtr<ArchiveResource> > subresources; documentLoader->getSubresources(subresources); return LegacyWebArchive::create(documentLoader->mainResource(), subresources, subframeArchives);}PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(Range* range){ if (!range) return 0; Node* startContainer = range->startContainer(); if (!startContainer) return 0; Document* document = startContainer->document(); if (!document) return 0; Frame* frame = document->frame(); if (!frame) return 0; Vector<Node*> nodeList; // FIXME: This is always "for interchange". Is that right? See the previous method. String markupString = frame->documentTypeString() + createMarkup(range, &nodeList, AnnotateForInterchange); return create(markupString, frame, nodeList);}PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Frame* frame, Vector<Node*>& nodes){ ASSERT(frame); const ResourceResponse& response = frame->loader()->documentLoader()->response(); KURL responseURL = response.url(); // it's possible to have a response without a URL here // <rdar://problem/5454935> if (responseURL.isNull()) responseURL = KURL(""); PassRefPtr<ArchiveResource> mainResource = ArchiveResource::create(utf8Buffer(markupString), responseURL, response.mimeType(), "UTF-8", frame->tree()->name()); Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; Vector<PassRefPtr<ArchiveResource> > subresources; HashSet<KURL> uniqueSubresources; Vector<Node*>::iterator it = nodes.begin(); Vector<Node*>::iterator end = nodes.end(); for (; it != end; ++it) { Frame* childFrame; if (((*it)->hasTagName(HTMLNames::frameTag) || (*it)->hasTagName(HTMLNames::iframeTag) || (*it)->hasTagName(HTMLNames::objectTag)) && (childFrame = static_cast<HTMLFrameOwnerElement*>(*it)->contentFrame())) { RefPtr<LegacyWebArchive> subframeArchive; subframeArchive = LegacyWebArchive::create(childFrame->document()); if (subframeArchive) subframeArchives.append(subframeArchive); else LOG_ERROR("Unabled to archive subframe %s", childFrame->tree()->name().string().utf8().data()); } else { ListHashSet<KURL> subresourceURLs; (*it)->getSubresourceURLs(subresourceURLs); DocumentLoader* documentLoader = frame->loader()->documentLoader(); ListHashSet<KURL>::iterator iterEnd = subresourceURLs.end(); for (ListHashSet<KURL>::iterator iter = subresourceURLs.begin(); iter != iterEnd; ++iter) { const KURL& subresourceURL = *iter; if (uniqueSubresources.contains(subresourceURL)) continue; uniqueSubresources.add(subresourceURL); RefPtr<ArchiveResource> resource = documentLoader->subresource(subresourceURL); if (resource) { subresources.append(resource.release()); continue; } CachedResource *cachedResource = cache()->resourceForURL(subresourceURL); if (cachedResource) { resource = ArchiveResource::create(cachedResource->data(), subresourceURL, cachedResource->response()); if (resource) { subresources.append(resource.release()); continue; } } // FIXME: should do something better than spew to console here LOG_ERROR("Failed to archive subresource for %s", subresourceURL.string().utf8().data()); } } } // Add favicon if one exists for this page if (iconDatabase() && iconDatabase()->isEnabled()) { const String& iconURL = iconDatabase()->iconURLForPageURL(responseURL); if (!iconURL.isEmpty() && iconDatabase()->iconDataKnownForIconURL(iconURL)) { if (Image* iconImage = iconDatabase()->iconForPageURL(responseURL, IntSize(16, 16))) { RefPtr<ArchiveResource> resource = ArchiveResource::create(iconImage->data(), KURL(iconURL), "image/x-icon", "", ""); subresources.append(resource.release()); } } } return create(mainResource, subresources, subframeArchives);}PassRefPtr<LegacyWebArchive> LegacyWebArchive::createFromSelection(Frame* frame){ if (!frame) return 0; RefPtr<Range> selectionRange = frame->selection()->toNormalizedRange(); Vector<Node*> nodeList; String markupString = frame->documentTypeString() + createMarkup(selectionRange.get(), &nodeList, AnnotateForInterchange); RefPtr<LegacyWebArchive> archive = create(markupString, frame, nodeList); if (!frame->document() || !frame->document()->isFrameSet()) return archive.release(); // Wrap the frameset document in an iframe so it can be pasted into // another document (which will have a body or frameset of its own). String iframeMarkup = String::format("<iframe frameborder=\"no\" marginwidth=\"0\" marginheight=\"0\" width=\"98%%\" height=\"98%%\" src=\"%s\"></iframe>", frame->loader()->documentLoader()->response().url().string().utf8().data()); RefPtr<ArchiveResource> iframeResource = ArchiveResource::create(utf8Buffer(iframeMarkup), blankURL(), "text/html", "UTF-8", String()); Vector<PassRefPtr<ArchiveResource> > subresources; Vector<PassRefPtr<LegacyWebArchive> > subframeArchives; subframeArchives.append(archive); archive = LegacyWebArchive::create(iframeResource.release(), subresources, subframeArchives); return archive.release();}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -