1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 */ 31 32 #include "config.h" 33 #include "core/loader/Prerenderer.h" 34 35 #include "core/dom/Document.h" 36 #include "core/loader/FrameLoader.h" 37 #include "core/loader/PrerendererClient.h" 38 #include "core/page/Frame.h" 39 #include "core/platform/PrerenderHandle.h" 40 #include "weborigin/ReferrerPolicy.h" 41 #include "weborigin/SecurityPolicy.h" 42 43 #include "wtf/PassOwnPtr.h" 44 #include "wtf/PassRefPtr.h" 45 #include "wtf/RefPtr.h" 46 #include "wtf/text/WTFString.h" 47 48 namespace WebCore { 49 50 // static 51 PassOwnPtr<Prerenderer> Prerenderer::create(Document* document) 52 { 53 Prerenderer* prerenderer = new Prerenderer(document); 54 prerenderer->suspendIfNeeded(); 55 return adoptPtr(prerenderer); 56 } 57 58 Prerenderer::Prerenderer(Document* document) 59 : ActiveDOMObject(document) 60 , m_initializedClient(false) 61 , m_client(0) 62 { 63 } 64 65 Prerenderer::~Prerenderer() 66 { 67 } 68 69 PassRefPtr<PrerenderHandle> Prerenderer::render(PrerenderClient* prerenderClient, const KURL& url) 70 { 71 // Prerenders are unlike requests in most ways (for instance, they pass down fragments, and they don't return data), 72 // but they do have referrers. 73 const ReferrerPolicy referrerPolicy = document()->referrerPolicy(); 74 75 if (!document()->frame()) 76 return 0; 77 78 const String referrer = SecurityPolicy::generateReferrerHeader(referrerPolicy, url, document()->frame()->loader()->outgoingReferrer()); 79 80 RefPtr<PrerenderHandle> prerenderHandle = PrerenderHandle::create(prerenderClient, url, referrer, referrerPolicy); 81 82 if (client()) 83 client()->willAddPrerender(prerenderHandle.get()); 84 prerenderHandle->add(); 85 86 m_activeHandles.append(prerenderHandle); 87 return prerenderHandle; 88 } 89 90 void Prerenderer::stop() 91 { 92 while (!m_activeHandles.isEmpty()) { 93 RefPtr<PrerenderHandle> handle = m_activeHandles[0].release(); 94 m_activeHandles.remove(0); 95 handle->abandon(); 96 } 97 while (!m_suspendedHandles.isEmpty()) { 98 RefPtr<PrerenderHandle> handle = m_suspendedHandles[0].release(); 99 m_suspendedHandles.remove(0); 100 handle->abandon(); 101 } 102 } 103 104 void Prerenderer::suspend(ReasonForSuspension reason) 105 { 106 if (reason == DocumentWillBecomeInactive) { 107 while (!m_activeHandles.isEmpty()) { 108 RefPtr<PrerenderHandle> handle = m_activeHandles[0].release(); 109 m_activeHandles.remove(0); 110 handle->suspend(); 111 m_suspendedHandles.append(handle); 112 } 113 } 114 } 115 116 void Prerenderer::resume() 117 { 118 while (!m_suspendedHandles.isEmpty()) { 119 RefPtr<PrerenderHandle> handle = m_suspendedHandles[0].release(); 120 m_suspendedHandles.remove(0); 121 handle->resume(); 122 m_activeHandles.append(handle); 123 } 124 } 125 126 Document* Prerenderer::document() 127 { 128 ASSERT(scriptExecutionContext()->isDocument()); 129 return toDocument(scriptExecutionContext()); 130 } 131 132 PrerendererClient* Prerenderer::client() 133 { 134 if (!m_initializedClient) { 135 // We can't initialize the client in our contructor, because the platform might not have 136 // provided our supplement by then. 137 m_initializedClient = true; 138 m_client = PrerendererClient::from(document()->page()); 139 } 140 return m_client; 141 } 142 143 } 144