1/* 2 * Copyright (C) 2012-2014 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "PlugInAutoStartProvider.h" 28 29#include "APIArray.h" 30#include "ImmutableDictionary.h" 31#include "WebContext.h" 32#include "WebContextClient.h" 33#include "WebProcessMessages.h" 34#include <wtf/CurrentTime.h> 35 36using namespace WebCore; 37 38static const double plugInAutoStartExpirationTimeThreshold = 30 * 24 * 60 * 60; 39 40namespace WebKit { 41 42PlugInAutoStartProvider::PlugInAutoStartProvider(WebContext* context) 43 : m_context(context) 44{ 45 m_hashToOriginMap.add(SessionID::defaultSessionID(), HashMap<unsigned, String>()); 46 m_autoStartTable.add(SessionID::defaultSessionID(), AutoStartTable()); 47} 48 49static double expirationTimeFromNow() 50{ 51 return currentTime() + plugInAutoStartExpirationTimeThreshold; 52} 53 54void PlugInAutoStartProvider::addAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash, SessionID sessionID) 55{ 56 auto sessionIterator = m_hashToOriginMap.find(sessionID); 57 if (sessionIterator == m_hashToOriginMap.end()) { 58 if (m_hashToOriginMap.get(SessionID::defaultSessionID()).contains(plugInOriginHash)) 59 return; 60 sessionIterator = m_hashToOriginMap.set(sessionID, HashMap<unsigned, String>()).iterator; 61 } else if (sessionIterator->value.contains(plugInOriginHash) || m_hashToOriginMap.get(SessionID::defaultSessionID()).contains(plugInOriginHash)) 62 return; 63 64 AutoStartTable::iterator it = m_autoStartTable.add(sessionID, AutoStartTable()).iterator->value.add(pageOrigin, PlugInAutoStartOriginMap()).iterator; 65 66 double expirationTime = expirationTimeFromNow(); 67 it->value.set(plugInOriginHash, expirationTime); 68 sessionIterator->value.set(plugInOriginHash, pageOrigin); 69 70 m_context->sendToAllProcesses(Messages::WebProcess::DidAddPlugInAutoStartOriginHash(plugInOriginHash, expirationTime, sessionID)); 71 72 if (!sessionID.isEphemeral()) 73 m_context->client().plugInAutoStartOriginHashesChanged(m_context); 74} 75 76SessionPlugInAutoStartOriginMap PlugInAutoStartProvider::autoStartOriginHashesCopy() const 77{ 78 SessionPlugInAutoStartOriginMap sessionMap; 79 80 for (const auto& sessionKeyOriginHash : m_autoStartTable) { 81 PlugInAutoStartOriginMap& map = sessionMap.add(sessionKeyOriginHash.key, PlugInAutoStartOriginMap()).iterator->value; 82 for (const auto& keyOriginHash : sessionKeyOriginHash.value) { 83 for (const auto& originHash : keyOriginHash.value) 84 map.set(originHash.key, originHash.value); 85 } 86 } 87 return sessionMap; 88} 89 90PassRefPtr<ImmutableDictionary> PlugInAutoStartProvider::autoStartOriginsTableCopy() const 91{ 92 ImmutableDictionary::MapType map; 93 94 double now = currentTime(); 95 for (const auto& stringOriginHash : m_autoStartTable.get(SessionID::defaultSessionID())) { 96 ImmutableDictionary::MapType hashMap; 97 for (const auto& originHash : stringOriginHash.value) { 98 if (now <= originHash.value) 99 hashMap.set(String::number(originHash.key), API::Double::create(originHash.value)); 100 } 101 if (hashMap.size()) 102 map.set(stringOriginHash.key, ImmutableDictionary::create(WTF::move(hashMap))); 103 } 104 105 return ImmutableDictionary::create(WTF::move(map)); 106} 107 108void PlugInAutoStartProvider::setAutoStartOriginsTable(ImmutableDictionary& table) 109{ 110 setAutoStartOriginsTableWithItemsPassingTest(table, [](double) { 111 return true; 112 }); 113} 114 115void PlugInAutoStartProvider::setAutoStartOriginsFilteringOutEntriesAddedAfterTime(ImmutableDictionary& table, double time) 116{ 117 double adjustedTimestamp = time + plugInAutoStartExpirationTimeThreshold; 118 setAutoStartOriginsTableWithItemsPassingTest(table, [adjustedTimestamp](double expirationTimestamp) { 119 return adjustedTimestamp > expirationTimestamp; 120 }); 121} 122 123void PlugInAutoStartProvider::setAutoStartOriginsTableWithItemsPassingTest(ImmutableDictionary& table, std::function<bool(double expirationTimestamp)> isExpirationTimeAcceptable) 124{ 125 ASSERT(isExpirationTimeAcceptable); 126 127 m_hashToOriginMap.clear(); 128 m_autoStartTable.clear(); 129 HashMap<unsigned, double> hashMap; 130 HashMap<unsigned, String>& hashToOriginMap = m_hashToOriginMap.add(SessionID::defaultSessionID(), HashMap<unsigned, String>()).iterator->value; 131 AutoStartTable& ast = m_autoStartTable.add(SessionID::defaultSessionID(), AutoStartTable()).iterator->value; 132 133 for (auto& strDict : table.map()) { 134 PlugInAutoStartOriginMap hashes; 135 for (auto& hashTime : static_cast<ImmutableDictionary*>(strDict.value.get())->map()) { 136 bool ok; 137 unsigned hash = hashTime.key.toUInt(&ok); 138 if (!ok) 139 continue; 140 141 if (hashTime.value->type() != API::Double::APIType) 142 continue; 143 144 double expirationTime = static_cast<API::Double*>(hashTime.value.get())->value(); 145 if (!isExpirationTimeAcceptable(expirationTime)) 146 continue; 147 148 hashes.set(hash, expirationTime); 149 hashMap.set(hash, expirationTime); 150 hashToOriginMap.set(hash, strDict.key); 151 } 152 153 if (!hashes.isEmpty()) 154 ast.set(strDict.key, hashes); 155 } 156 157 m_context->sendToAllProcesses(Messages::WebProcess::ResetPlugInAutoStartOriginDefaultHashes(hashMap)); 158} 159 160void PlugInAutoStartProvider::setAutoStartOriginsArray(API::Array& originList) 161{ 162 m_autoStartOrigins.clear(); 163 for (const auto& string : originList.elementsOfType<API::String>()) 164 m_autoStartOrigins.append(string->string()); 165} 166 167void PlugInAutoStartProvider::didReceiveUserInteraction(unsigned plugInOriginHash, SessionID sessionID) 168{ 169 HashMap<WebCore::SessionID, HashMap<unsigned, String>>::const_iterator sessionIterator = m_hashToOriginMap.find(sessionID); 170 HashMap<unsigned, String>::const_iterator it; 171 bool contains = false; 172 if (sessionIterator != m_hashToOriginMap.end()) { 173 it = sessionIterator->value.find(plugInOriginHash); 174 contains = it != sessionIterator->value.end(); 175 } 176 if (!contains) { 177 sessionIterator = m_hashToOriginMap.find(SessionID::defaultSessionID()); 178 it = sessionIterator->value.find(plugInOriginHash); 179 if (it == sessionIterator->value.end()) { 180 ASSERT_NOT_REACHED(); 181 return; 182 } 183 } 184 185 double newExpirationTime = expirationTimeFromNow(); 186 m_autoStartTable.add(sessionID, AutoStartTable()).iterator->value.add(it->value, PlugInAutoStartOriginMap()).iterator->value.set(plugInOriginHash, newExpirationTime); 187 m_context->sendToAllProcesses(Messages::WebProcess::DidAddPlugInAutoStartOriginHash(plugInOriginHash, newExpirationTime, sessionID)); 188 m_context->client().plugInAutoStartOriginHashesChanged(m_context); 189} 190 191} // namespace WebKit 192