1d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter/* 2d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * Copyright 2010, The Android Open Source Project 3d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * 4d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * Redistribution and use in source and binary forms, with or without 5d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * modification, are permitted provided that the following conditions 6d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * are met: 7d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * * Redistributions of source code must retain the above copyright 8d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * notice, this list of conditions and the following disclaimer. 9d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * * Redistributions in binary form must reproduce the above copyright 10d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * notice, this list of conditions and the following disclaimer in the 11d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * documentation and/or other materials provided with the distribution. 12d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * 13d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter */ 25d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 26d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#define LOG_TAG "webarchive" 27d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 28d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include "config.h" 29d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include "WebArchiveAndroid.h" 30d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 31d73b16bdebb9d20b17be0a30e626dc9e66b6d868Steve Block#if ENABLE(WEB_ARCHIVE) 325dc3f82ee1d379f4df8606cdf60369965b44486cSteve Block 33d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include "Base64.h" 34d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include <libxml/encoding.h> 35d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include <libxml/parser.h> 36d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include <libxml/tree.h> 37d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include <libxml/xmlstring.h> 38d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include <libxml/xmlwriter.h> 3930a9d6dfa5ddf75aef0fcf23f7bfbffa41a704ffSteve Block#include <utils/Log.h> 40d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter#include <wtf/text/CString.h> 41d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 42d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughternamespace WebCore { 43d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 44d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const archiveTag = BAD_CAST "Archive"; 45d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const archiveResourceTag = BAD_CAST "ArchiveResource"; 46d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const mainResourceTag = BAD_CAST "mainResource"; 47d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const subresourcesTag = BAD_CAST "subresources"; 48d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const subframesTag = BAD_CAST "subframes"; 49d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const urlFieldTag = BAD_CAST "url"; 50d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const mimeFieldTag = BAD_CAST "mimeType"; 51d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const encodingFieldTag = BAD_CAST "textEncoding"; 52d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const frameFieldTag = BAD_CAST "frameName"; 53d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic const xmlChar* const dataFieldTag = BAD_CAST "data"; 54d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 55d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott SlaughterPassRefPtr<WebArchiveAndroid> WebArchiveAndroid::create(PassRefPtr<ArchiveResource> mainResource, 56d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<ArchiveResource> >& subresources, 57d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<Archive> >& subframeArchives) 58d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 59320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter if (mainResource) 60d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return adoptRef(new WebArchiveAndroid(mainResource, subresources, subframeArchives)); 61320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 62d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 63d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 64d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott SlaughterPassRefPtr<WebArchiveAndroid> WebArchiveAndroid::create(Frame* frame) 65d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 66d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter PassRefPtr<ArchiveResource> mainResource = frame->loader()->documentLoader()->mainResource(); 67d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<ArchiveResource> > subresources; 68d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<Archive> > subframes; 69d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter int children = frame->tree()->childCount(); 70d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 71d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter frame->loader()->documentLoader()->getSubresources(subresources); 72d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 73320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter for (int child = 0; child < children; child++) 74d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subframes.append(create(frame->tree()->child(child))); 75d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 76d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return create(mainResource, subresources, subframes); 77d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 78d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 79d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott SlaughterWebArchiveAndroid::WebArchiveAndroid(PassRefPtr<ArchiveResource> mainResource, 80d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<ArchiveResource> >& subresources, 81d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<Archive> >& subframeArchives) 82d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 83d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter setMainResource(mainResource); 84d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 85d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (Vector<PassRefPtr<ArchiveResource> >::iterator subresourcesIterator = subresources.begin(); 86d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subresourcesIterator != subresources.end(); 87d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subresourcesIterator++) { 88d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter addSubresource(*subresourcesIterator); 89d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 90d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 91d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (Vector<PassRefPtr<Archive> >::iterator subframesIterator = subframeArchives.begin(); 92d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subframesIterator != subframeArchives.end(); 93d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subframesIterator++) { 94d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter addSubframeArchive(*subframesIterator); 95d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 96d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 97d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 98d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic bool loadArchiveResourceField(xmlNodePtr resourceNode, const xmlChar* fieldName, Vector<char>* outputData) 99d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 100d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!outputData) 101d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 102d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 103d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter outputData->clear(); 104d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 105320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter const char* base64Data = 0; 106d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 107d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (xmlNodePtr fieldNode = resourceNode->xmlChildrenNode; 108320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter fieldNode; 109d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter fieldNode = fieldNode->next) { 110d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (xmlStrEqual(fieldNode->name, fieldName)) { 111d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter base64Data = (const char*)xmlNodeGetContent(fieldNode->xmlChildrenNode); 112d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!base64Data) { 113d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter /* Empty fields seem to break if they aren't null terminated. */ 114d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter outputData->append('\0'); 115d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return true; 116d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 117d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter break; 118d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 119d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 120d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!base64Data) { 121a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResourceField: Failed to load field."); 122d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 123d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 124d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 125d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter const int base64Size = xmlStrlen(BAD_CAST base64Data); 126d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 127d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter const int result = base64Decode(base64Data, base64Size, *outputData); 128d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!result) { 129a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResourceField: Failed to decode field."); 130d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 131d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 132d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 133d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return true; 134d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 135d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 136d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic PassRefPtr<SharedBuffer> loadArchiveResourceFieldBuffer(xmlNodePtr resourceNode, const xmlChar* fieldName) 137d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 138d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<char> fieldData; 139d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 140d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (loadArchiveResourceField(resourceNode, fieldName, &fieldData)) 141d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return SharedBuffer::create(fieldData.data(), fieldData.size()); 142d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 143320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 144d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 145d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 146d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic String loadArchiveResourceFieldString(xmlNodePtr resourceNode, const xmlChar* fieldName) 147d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 148d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<char> fieldData; 149d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 150d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (loadArchiveResourceField(resourceNode, fieldName, &fieldData)) 151d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return String::fromUTF8(fieldData.data(), fieldData.size()); 152d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 153d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return String(); 154d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 155d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 156d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic KURL loadArchiveResourceFieldURL(xmlNodePtr resourceNode, const xmlChar* fieldName) 157d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 158d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<char> fieldData; 159d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 160d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (loadArchiveResourceField(resourceNode, fieldName, &fieldData)) 161d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return KURL(ParsedURLString, String::fromUTF8(fieldData.data(), fieldData.size())); 162d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 163d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return KURL(); 164d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 165d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 166d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic PassRefPtr<ArchiveResource> loadArchiveResource(xmlNodePtr resourceNode) 167d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 168d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!xmlStrEqual(resourceNode->name, archiveResourceTag)) { 169a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResource: Malformed resource."); 170320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 171d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 172d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 173d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter KURL url = loadArchiveResourceFieldURL(resourceNode, urlFieldTag); 174d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (url.isNull()) { 175a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResource: Failed to load resource."); 176320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 177d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 178d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 179d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter String mimeType = loadArchiveResourceFieldString(resourceNode, mimeFieldTag); 180d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (mimeType.isNull()) { 181a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResource: Failed to load resource."); 182320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 183d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 184d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 185d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter String textEncoding = loadArchiveResourceFieldString(resourceNode, encodingFieldTag); 186d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (textEncoding.isNull()) { 187a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResource: Failed to load resource."); 188320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 189d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 190d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 191d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter String frameName = loadArchiveResourceFieldString(resourceNode, frameFieldTag); 192d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (frameName.isNull()) { 193a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResource: Failed to load resource."); 194320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 195d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 196d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 197d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter PassRefPtr<SharedBuffer> data = loadArchiveResourceFieldBuffer(resourceNode, dataFieldTag); 198d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!data) { 199a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchiveResource: Failed to load resource."); 200320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 201d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 202d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 203d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return ArchiveResource::create(data, url, mimeType, textEncoding, frameName); 204d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 205d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 206d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic PassRefPtr<WebArchiveAndroid> loadArchive(xmlNodePtr archiveNode) 207d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 208320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter xmlNodePtr resourceNode = 0; 209d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 210d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter PassRefPtr<ArchiveResource> mainResource; 211d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<ArchiveResource> > subresources; 212d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<Archive> > subframes; 213d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 214d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!xmlStrEqual(archiveNode->name, archiveTag)) { 215a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchive: Malformed archive."); 216320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 217d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 218d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 219d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (resourceNode = archiveNode->xmlChildrenNode; 220320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter resourceNode; 221d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter resourceNode = resourceNode->next) { 222d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (xmlStrEqual(resourceNode->name, mainResourceTag)) { 223d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter resourceNode = resourceNode->xmlChildrenNode; 224320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter if (!resourceNode) 225d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter break; 226d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter mainResource = loadArchiveResource(resourceNode); 227d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter break; 228d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 229d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 230d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!mainResource) { 231a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchive: Failed to load main resource."); 232320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter return 0; 233d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 234d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 235d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (resourceNode = archiveNode->xmlChildrenNode; 236320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter resourceNode; 237d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter resourceNode = resourceNode->next) { 238d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (xmlStrEqual(resourceNode->name, subresourcesTag)) { 239d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (resourceNode = resourceNode->xmlChildrenNode; 240320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter resourceNode; 241d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter resourceNode = resourceNode->next) { 242d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter PassRefPtr<ArchiveResource> subresource = loadArchiveResource(resourceNode); 243d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!subresource) { 244a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchive: Failed to load subresource."); 245d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter break; 246d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 247d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subresources.append(subresource); 248d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 249d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter break; 250d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 251d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 252d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 253d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (resourceNode = archiveNode->xmlChildrenNode; 254320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter resourceNode; 255d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter resourceNode = resourceNode->next) { 256d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (xmlStrEqual(resourceNode->name, subframesTag)) { 257d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (resourceNode = resourceNode->xmlChildrenNode; 258320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter resourceNode; 259d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter resourceNode = resourceNode->next) { 260d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter PassRefPtr<WebArchiveAndroid> subframe = loadArchive(resourceNode); 261d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!subframe) { 262a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("loadArchive: Failed to load subframe."); 263d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter break; 264d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 265d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subframes.append(subframe); 266d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 267d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter break; 268d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 269d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 270d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 271d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return WebArchiveAndroid::create(mainResource, subresources, subframes); 272d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 273d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 274320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughterstatic PassRefPtr<WebArchiveAndroid> createArchiveForError() 275320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter{ 276d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter /* When an archive cannot be loaded, we return an empty archive instead. */ 277d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter PassRefPtr<ArchiveResource> mainResource = ArchiveResource::create( 278d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter SharedBuffer::create(), KURL(ParsedURLString, String::fromUTF8("file:///dummy")), 279d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter String::fromUTF8("text/plain"), String(""), String("")); 280d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<ArchiveResource> > subresources; 281d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<PassRefPtr<Archive> > subframes; 282d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 283d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return WebArchiveAndroid::create(mainResource, subresources, subframes); 284d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 285d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 286d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott SlaughterPassRefPtr<WebArchiveAndroid> WebArchiveAndroid::create(SharedBuffer* buffer) 287d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 288d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter const char* const noBaseUrl = ""; 289320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter const char* const defaultEncoding = 0; 290d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter const int noParserOptions = 0; 291d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 292d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter xmlDocPtr doc = xmlReadMemory(buffer->data(), buffer->size(), noBaseUrl, defaultEncoding, noParserOptions); 293320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter if (!doc) { 294a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("create: Failed to parse document."); 295d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return createArchiveForError(); 296d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 297d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 298d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter xmlNodePtr root = xmlDocGetRootElement(doc); 299320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter if (!root) { 300a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("create: Empty document."); 301d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter xmlFreeDoc(doc); 302d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return createArchiveForError(); 303d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 304d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 305d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter RefPtr<WebArchiveAndroid> archive = loadArchive(root); 306d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!archive) { 307a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("create: Failed to load archive."); 308d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter xmlFreeDoc(doc); 309d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return createArchiveForError(); 310d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 311d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 312d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter xmlFreeDoc(doc); 313d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return archive.release(); 314d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 315d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 316d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic bool saveArchiveResourceField(xmlTextWriterPtr writer, const xmlChar* tag, const char* data, int size) 317d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 318d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter int result = xmlTextWriterStartElement(writer, tag); 319d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 320a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchiveResourceField: Failed to start element."); 321d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 322d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 323d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 324d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (size > 0) { 325d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter Vector<char> base64Data; 326d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter base64Encode(data, size, base64Data, false); 327d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (base64Data.isEmpty()) { 328a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchiveResourceField: Failed to base64 encode data."); 329d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 330d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 331d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 332d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterWriteRawLen(writer, BAD_CAST base64Data.data(), base64Data.size()); 333d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 334a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchiveResourceField: Failed to write data."); 335d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 336d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 337d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 338d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 339d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterEndElement(writer); 340d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 341a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchiveResourceField: Failed to end element."); 342d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 343d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 344d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 345d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return true; 346d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 347d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 348d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic bool saveArchiveResourceField(xmlTextWriterPtr writer, const xmlChar* tag, SharedBuffer* buffer) 349d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 350d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return saveArchiveResourceField(writer, tag, buffer->data(), buffer->size()); 351d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 352d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 353d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic bool saveArchiveResourceField(xmlTextWriterPtr writer, const xmlChar* tag, const String& string) 354d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 355d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter CString utf8String = string.utf8(); 356d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 357d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return saveArchiveResourceField(writer, tag, utf8String.data(), utf8String.length()); 358d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 359d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 360d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughterstatic bool saveArchiveResource(xmlTextWriterPtr writer, PassRefPtr<ArchiveResource> resource) 361d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter{ 362d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter int result = xmlTextWriterStartElement(writer, archiveResourceTag); 363d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 364a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchiveResource: Failed to start element."); 365d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 366d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 367d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 368d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!saveArchiveResourceField(writer, urlFieldTag, resource->url().string()) 369d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter || !saveArchiveResourceField(writer, mimeFieldTag, resource->mimeType()) 370d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter || !saveArchiveResourceField(writer, encodingFieldTag, resource->textEncoding()) 371d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter || !saveArchiveResourceField(writer, frameFieldTag, resource->frameName()) 372d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter || !saveArchiveResourceField(writer, dataFieldTag, resource->data())) 373d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 374d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 375d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterEndElement(writer); 376d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 377a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchiveResource: Failed to end element."); 378d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 379d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 380d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 381d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return true; 382d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 383d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 384320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughterstatic bool saveArchive(xmlTextWriterPtr writer, PassRefPtr<Archive> archive) 385320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter{ 386d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter int result = xmlTextWriterStartElement(writer, archiveTag); 387d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 388a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchive: Failed to start element."); 389d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 390d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 391d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 392d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterStartElement(writer, mainResourceTag); 393d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 394a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchive: Failed to start element."); 395d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 396d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 397d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 398d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!saveArchiveResource(writer, archive->mainResource())) 399d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 400d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 401d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterEndElement(writer); 402d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 403a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchive: Failed to end element."); 404d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 405d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 406d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 407d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterStartElement(writer, subresourcesTag); 408d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 409a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchive: Failed to start element."); 410d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 411d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 412d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 413d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (Vector<const RefPtr<ArchiveResource> >::iterator subresource = archive->subresources().begin(); 414d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subresource != archive->subresources().end(); 415d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subresource++) { 416d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!saveArchiveResource(writer, *subresource)) 417d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 418d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 419d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 420d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterEndElement(writer); 421d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 422a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchive: Failed to end element."); 423d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 424d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 425d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 426d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterStartElement(writer, subframesTag); 427d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 428a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchive: Failed to start element."); 429d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 430d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 431d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 432d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter for (Vector<const RefPtr<Archive> >::iterator subframe = archive->subframeArchives().begin(); 433d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subframe != archive->subframeArchives().end(); 434d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter subframe++) { 435320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter if (!saveArchive(writer, *subframe)) 436d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 437d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 438d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 439d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterEndElement(writer); 440d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 441a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveArchive: Failed to end element."); 442d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return true; 443d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 444d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 445d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return true; 446d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 447d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 448320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughterbool WebArchiveAndroid::saveWebArchive(xmlTextWriterPtr writer) 449320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter{ 450320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter const char* const defaultXmlVersion = 0; 451320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter const char* const defaultEncoding = 0; 452320d49d8900163ea450b99f106701a3455fb1bb6Elliott Slaughter const char* const defaultStandalone = 0; 453d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 454d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter int result = xmlTextWriterStartDocument(writer, defaultXmlVersion, defaultEncoding, defaultStandalone); 455d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result < 0) { 456a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveWebArchive: Failed to start document."); 457d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 458d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 459d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 460d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (!saveArchive(writer, this)) 461d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 462d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 463d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter result = xmlTextWriterEndDocument(writer); 464d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter if (result< 0) { 465a09e7cf49f43950a799f936bf42a9912d696547bSteve Block ALOGD("saveWebArchive: Failed to end document."); 466d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return false; 467d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter } 468d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 469d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter return true; 470d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 471d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter 472d66cc5d8dc3be3dcfc78f5155cf9f7b8015ee7b4Elliott Slaughter} 4735dc3f82ee1d379f4df8606cdf60369965b44486cSteve Block 474d73b16bdebb9d20b17be0a30e626dc9e66b6d868Steve Block#endif // ENABLE(WEB_ARCHIVE) 475