void PageSerializer::serializeFrame(Frame* frame) { Document* document = frame->document(); URL url = document->url(); if (!url.isValid() || url.isBlankURL()) { // For blank frames we generate a fake URL so they can be referenced by their containing frame. url = urlForBlankFrame(frame); } if (m_resourceURLs.contains(url)) { // FIXME: We could have 2 frame with the same URL but which were dynamically changed and have now // different content. So we should serialize both and somehow rename the frame src in the containing // frame. Arg! return; } Vector<Node*> nodes; SerializerMarkupAccumulator accumulator(*this, *document, &nodes); TextEncoding textEncoding(document->charset()); CString data; if (!textEncoding.isValid()) { // FIXME: iframes used as images trigger this. We should deal with them correctly. return; } String text = accumulator.serializeNodes(*document->documentElement(), 0, IncludeNode); CString frameHTML = textEncoding.encode(text, EntitiesForUnencodables); m_resources->append(Resource(url, document->suggestedMIMEType(), SharedBuffer::create(frameHTML.data(), frameHTML.length()))); m_resourceURLs.add(url); for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) { Node* node = *iter; if (!is<Element>(*node)) continue; Element& element = downcast<Element>(*node); // We have to process in-line style as it might contain some resources (typically background images). if (is<StyledElement>(element)) retrieveResourcesForProperties(downcast<StyledElement>(element).inlineStyle(), document); if (is<HTMLImageElement>(element)) { HTMLImageElement& imageElement = downcast<HTMLImageElement>(element); URL url = document->completeURL(imageElement.fastGetAttribute(HTMLNames::srcAttr)); CachedImage* cachedImage = imageElement.cachedImage(); addImageToResources(cachedImage, imageElement.renderer(), url); } else if (is<HTMLLinkElement>(element)) { HTMLLinkElement& linkElement = downcast<HTMLLinkElement>(element); if (CSSStyleSheet* sheet = linkElement.sheet()) { URL url = document->completeURL(linkElement.getAttribute(HTMLNames::hrefAttr)); serializeCSSStyleSheet(sheet, url); ASSERT(m_resourceURLs.contains(url)); } } else if (is<HTMLStyleElement>(element)) { if (CSSStyleSheet* sheet = downcast<HTMLStyleElement>(element).sheet()) serializeCSSStyleSheet(sheet, URL()); } } for (Frame* childFrame = frame->tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) serializeFrame(childFrame); }
void PageSerializer::serializeCSSStyleSheet(CSSStyleSheet* styleSheet, const KURL& url) { StringBuilder cssText; for (unsigned i = 0; i < styleSheet->length(); ++i) { CSSRule* rule = styleSheet->item(i); String itemText = rule->cssText(); if (!itemText.isEmpty()) { cssText.append(itemText); if (i < styleSheet->length() - 1) cssText.append("\n\n"); } Document* document = styleSheet->ownerDocument(); // Some rules have resources associated with them that we need to retrieve. if (rule->type() == CSSRule::IMPORT_RULE) { CSSImportRule* importRule = toCSSImportRule(rule); KURL importURL = document->completeURL(importRule->href()); if (m_resourceURLs.contains(importURL)) continue; serializeCSSStyleSheet(importRule->styleSheet(), importURL); } else if (rule->type() == CSSRule::FONT_FACE_RULE) { retrieveResourcesForProperties(toCSSFontFaceRule(rule)->styleRule()->properties(), document); } else if (rule->type() == CSSRule::STYLE_RULE) { retrieveResourcesForProperties(toCSSStyleRule(rule)->styleRule()->properties(), document); } } if (url.isValid() && !m_resourceURLs.contains(url)) { // FIXME: We should check whether a charset has been specified and if none was found add one. WTF::TextEncoding textEncoding(styleSheet->contents()->charset()); ASSERT(textEncoding.isValid()); String textString = cssText.toString(); CString text = textEncoding.normalizeAndEncode(textString, WTF::EntitiesForUnencodables); m_resources->append(SerializedResource(url, String("text/css"), SharedBuffer::create(text.data(), text.length()))); m_resourceURLs.add(url); } }
void PageSerializer::retrieveResourcesForRule(StyleRule* rule, Document* document) { retrieveResourcesForProperties(&rule->properties(), document); }