Home | History | Annotate | Download | only in loader
      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