TEST_F(SecurityOriginTest, UniquenessPropagatesToBlobUrls)
{
    struct TestCase {
        const char* url;
        bool expectedUniqueness;
        const char* expectedOriginString;
    } cases[] {
        { "", true, "null" },
        { "null", true, "null" },
        { "data:text/plain,hello_world", true, "null" },
        { "file:///path", false, "file://" },
        { "filesystem:http://host/filesystem-path", false, "http://host" },
        { "filesystem:file:///filesystem-path", false, "file://" },
        { "filesystem:null/filesystem-path", true, "null" },
        { "blob:http://host/blob-id", false, "http://host" },
        { "blob:file:///blob-id", false, "file://" },
        { "blob:null/blob-id", true, "null" },
    };

    for (const TestCase& test : cases) {
        RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(test.url);
        EXPECT_EQ(test.expectedUniqueness, origin->isUnique());
        EXPECT_EQ(test.expectedOriginString, origin->toString());

        KURL blobUrl = BlobURL::createPublicURL(origin.get());
        RefPtr<SecurityOrigin> blobUrlOrigin = SecurityOrigin::create(blobUrl);
        EXPECT_EQ(blobUrlOrigin->isUnique(), origin->isUnique());
        EXPECT_EQ(blobUrlOrigin->toString(), origin->toString());
        EXPECT_EQ(blobUrlOrigin->toRawString(), origin->toRawString());
    }
}
TEST(DatabaseIdentifierTest, CreateSecurityOriginFromIdentifier)
{
    struct IdentifierTestCase {
        String identifier;
        String expectedProtocol;
        String expectedHost;
        int expectedPort;
        String expectedStringRepresentation;
        bool expectedUnique;
    };

    IdentifierTestCase validCases[] = {
        {"http_google.com_0", "http", "google.com", 0, "http://google.com", false},
        {"https_google.com_0", "https", "google.com", 0, "https://google.com", false},
        {"ftp_google.com_0", "ftp", "google.com", 0, "ftp://google.com", false},
        {"unknown_google.com_0", "", "", 0, "null", true},
        {"http_nondefaultport.net_8001", "http", "nondefaultport.net", 8001, "http://nondefaultport.net:8001", false},
        {"file__0", "", "", 0, "null", true},
        {"__0", "", "", 0, "null", true},
        {"http_foo_bar_baz.org_0", "http", "foo_bar_baz.org", 0, "http://foo_bar_baz.org", false},
        {"http_xn--n3h.unicode.com_0", "http", "xn--n3h.unicode.com", 0, "http://xn--n3h.unicode.com", false},
        {"http_dot.com_0", "http", "dot.com", 0, "http://dot.com", false},
        {"http_escaped%3Dfun.com_0", "http", "escaped%3dfun.com", 0, "http://escaped%3dfun.com", false},
    };

    for (size_t i = 0; i < WTF_ARRAY_LENGTH(validCases); ++i) {
        RefPtr<SecurityOrigin> origin = createSecurityOriginFromDatabaseIdentifier(validCases[i].identifier);
        EXPECT_EQ(validCases[i].expectedProtocol, origin->protocol()) << "test case " << i;
        EXPECT_EQ(validCases[i].expectedHost, origin->host()) << "test case " << i;
        EXPECT_EQ(validCases[i].expectedPort, origin->port()) << "test case " << i;
        EXPECT_EQ(validCases[i].expectedStringRepresentation, origin->toString()) << "test case " << i;
        EXPECT_EQ(validCases[i].expectedUnique, origin->isUnique()) << "test case " << i;
    }

    String bogusIdentifiers[] = {
        "", "_", "__",
        String("\x00", 1),
        String("http_\x00_0", 8),
        "ht\x7ctp_badprotocol.com_0",
        "http_unescaped_percent_%.com_0",
        "http_port_too_big.net_75000",
        "http_port_too_small.net_-25",
        "http_shouldbeescaped\x7c.com_0",
        "http_latin1\x8a.org_8001",
        String::fromUTF8("http_\xe2\x98\x83.unicode.com_0"),
        "http_dot%252ecom_0",
        "HtTp_NonCanonicalRepresenTation_0",
        "http_non_ascii.\xa1.com_0",
        "http_not_canonical_escape%3d_0",
    };

    for (size_t i = 0; i < WTF_ARRAY_LENGTH(bogusIdentifiers); ++i) {
        RefPtr<SecurityOrigin> origin = createSecurityOriginFromDatabaseIdentifier(bogusIdentifiers[i]);
        EXPECT_EQ("null", origin->toString()) << "test case " << i;
        EXPECT_EQ(true, origin->isUnique()) << "test case " << i;
    }
}
void NotificationPermissionRequestManager::didReceiveNotificationPermissionDecision(uint64_t requestID, bool allowed)
{
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
    if (!isRequestIDValid(requestID))
        return;

    RefPtr<WebCore::SecurityOrigin> origin = m_idToOriginMap.take(requestID);
    m_originToIDMap.remove(origin);

    WebProcess::shared().notificationManager().didUpdateNotificationDecision(origin->toString(), allowed);

#if ENABLE(LEGACY_NOTIFICATIONS)
    RefPtr<VoidCallback> voidCallback = m_idToVoidCallbackMap.take(requestID);
    if (voidCallback) {
        voidCallback->handleEvent();
        return;
    }
#endif

#if ENABLE(NOTIFICATIONS)
    RefPtr<NotificationPermissionCallback> callback = m_idToCallbackMap.take(requestID);
    if (!callback)
        return;

    callback->handleEvent(Notification::permissionString(allowed ? NotificationClient::PermissionAllowed : NotificationClient::PermissionDenied));
#endif

#else
    UNUSED_PARAM(requestID);
    UNUSED_PARAM(allowed);
#endif
}
Example #4
0
void CookieManager::cookieLimitCleanUp(Timer<CookieManager>* timer)
{
    ASSERT_UNUSED(timer, timer == &m_limitTimer);

    CookieLimitLog("CookieManager - Starting cookie clean up");

    size_t numberOfCookiesOverLimit = (m_count > s_globalMaxCookieCount) ? m_count - s_globalMaxCookieCount : 0;
    size_t amountToDelete = s_cookiesToDeleteWhenLimitReached + numberOfCookiesOverLimit;

    CookieLimitLog("CookieManager - Excess: %d  Amount to Delete: %d", numberOfCookiesOverLimit, amountToDelete);

    // Call the database to delete 'amountToDelete' of cookies
    Vector<RefPtr<ParsedCookie> > cookiesToDelete;
    cookiesToDelete.reserveInitialCapacity(amountToDelete);

    CookieLimitLog("CookieManager - Calling database to clean up");
    m_cookieBackingStore->getCookiesFromDatabase(cookiesToDelete, amountToDelete);

    // Cookies are ordered in ASC order by lastAccessed
    for (size_t i = 0; i < amountToDelete; ++i) {
        // Expire them and call checkandtreat to delete them from memory and database
        RefPtr<ParsedCookie> newCookie = cookiesToDelete[i];
        CookieLimitLog("CookieManager - Expire cookie: %s and delete", newCookie->toString().utf8().data());
        newCookie->forceExpire();
        checkAndTreatCookie(newCookie, RemoveFromBackingStore);
    }

    CookieLimitLog("CookieManager - Cookie clean up complete.");
}
TEST(DatabaseIdentifierTest, CreateIdentifierFromSecurityOrigin)
{
    struct OriginTestCase {
        String protocol;
        String host;
        int port;
        String expectedIdentifier;
    } cases[] = {
        {"http", "google.com", 80, "http_google.com_0"},
        {"https", "www.google.com", 443, "https_www.google.com_0"},
        {"http", "foo_bar_baz.org", 80, "http_foo_bar_baz.org_0"},
        {"http", "nondefaultport.net", 8001, "http_nondefaultport.net_8001"},
        {"http", "invalidportnumber.org", 70000, "__0"},
        {"http", "invalidportnumber.org", -5, "__0"},
        {"http", "%E2%98%83.unicode.com", 80, "http_xn--n3h.unicode.com_0"},
        {"http", String::fromUTF8("\xe2\x98\x83.unicode.com"), 80, "http_xn--n3h.unicode.com_0"},
        {"http", String::fromUTF8("\xf0\x9f\x92\xa9.unicode.com"), 80, "http_xn--ls8h.unicode.com_0"},
        {"file", "", 0, "file__0"},
        {"data", "", 0, "__0"},
        {"about", "blank", 0, "__0"},
        {"non-standard", "foobar.com", 0, "non-standard__0"},
    };

    for (size_t i = 0; i < WTF_ARRAY_LENGTH(cases); ++i) {
        RefPtr<SecurityOrigin> origin = SecurityOrigin::create(cases[i].protocol, cases[i].host, cases[i].port);
        String identifier = createDatabaseIdentifierFromSecurityOrigin(origin.get());
        EXPECT_EQ(cases[i].expectedIdentifier, identifier) << "test case " << origin->toString();
    }
}
Example #6
0
TEST_F(SecurityOriginTest, SuboriginsParsing) {
  RuntimeEnabledFeatures::setSuboriginsEnabled(true);
  String protocol, realProtocol, host, realHost, suborigin;
  protocol = "https";
  host = "test.com";
  EXPECT_FALSE(SecurityOrigin::deserializeSuboriginAndProtocolAndHost(
      protocol, host, suborigin, realProtocol, realHost));

  protocol = "https-so";
  host = "foobar.test.com";
  EXPECT_TRUE(SecurityOrigin::deserializeSuboriginAndProtocolAndHost(
      protocol, host, suborigin, realProtocol, realHost));
  EXPECT_EQ("https", realProtocol);
  EXPECT_EQ("test.com", realHost);
  EXPECT_EQ("foobar", suborigin);

  RefPtr<SecurityOrigin> origin;
  StringBuilder builder;

  origin = SecurityOrigin::createFromString("https-so://foobar.test.com");
  origin->buildRawString(builder, true);
  EXPECT_EQ("https-so://foobar.test.com", builder.toString());
  EXPECT_EQ("https-so://foobar.test.com", origin->toString());
  builder.clear();
  origin->buildRawString(builder, false);
  EXPECT_EQ("https://test.com", builder.toString());
  EXPECT_EQ("https://test.com", origin->toPhysicalOriginString());

  Suborigin suboriginObj;
  suboriginObj.setName("foobar");
  builder.clear();
  origin = SecurityOrigin::createFromString("https://test.com");
  origin->addSuborigin(suboriginObj);
  origin->buildRawString(builder, true);
  EXPECT_EQ("https-so://foobar.test.com", builder.toString());
  EXPECT_EQ("https-so://foobar.test.com", origin->toString());
  builder.clear();
  origin->buildRawString(builder, false);
  EXPECT_EQ("https://test.com", builder.toString());
  EXPECT_EQ("https://test.com", origin->toPhysicalOriginString());
}
Example #7
0
static bool prettyPrintScript(ExecState* exec, const UString& fileName, const Vector<char>& script)
{
    int errLine = 0;
    UString errMsg;
    UString scriptUString(script.data());
    RefPtr<ProgramNode> programNode = exec->parser()->parse<ProgramNode>(exec, fileName, 1, UStringSourceProvider::create(scriptUString), 0, &errLine, &errMsg);
    if (!programNode) {
        fprintf(stderr, "%s:%d: %s.\n", fileName.UTF8String().c_str(), errLine, errMsg.UTF8String().c_str());
        return false;
    }

    printf("%s\n", programNode->toString().UTF8String().c_str());
    return true;
}
Example #8
0
void ServiceWorkerGlobalScopeProxy::dispatchForeignFetchEvent(
    int fetchEventID,
    const WebServiceWorkerRequest& webRequest) {
  if (!OriginTrials::foreignFetchEnabled(workerGlobalScope())) {
    // If origin trial tokens have expired, or are otherwise no longer valid
    // no events should be dispatched.
    // TODO(mek): Ideally the browser wouldn't even start the service worker
    // if its tokens have expired.
    ServiceWorkerGlobalScopeClient::from(workerGlobalScope())
        ->respondToFetchEvent(fetchEventID, WTF::currentTime());
    ServiceWorkerGlobalScopeClient::from(workerGlobalScope())
        ->didHandleFetchEvent(fetchEventID,
                              WebServiceWorkerEventResultCompleted,
                              WTF::currentTime());
    return;
  }

  ScriptState::Scope scope(
      workerGlobalScope()->scriptController()->getScriptState());
  RefPtr<SecurityOrigin> origin =
      SecurityOrigin::create(webRequest.referrerUrl());
  WaitUntilObserver* waitUntilObserver = WaitUntilObserver::create(
      workerGlobalScope(), WaitUntilObserver::Fetch, fetchEventID);
  ForeignFetchRespondWithObserver* respondWithObserver =
      ForeignFetchRespondWithObserver::create(
          workerGlobalScope(), fetchEventID, webRequest.url(),
          webRequest.mode(), webRequest.frameType(),
          webRequest.requestContext(), origin, waitUntilObserver);
  Request* request = Request::create(
      workerGlobalScope()->scriptController()->getScriptState(), webRequest);
  request->getHeaders()->setGuard(Headers::ImmutableGuard);
  ForeignFetchEventInit eventInit;
  eventInit.setCancelable(true);
  eventInit.setRequest(request);
  eventInit.setOrigin(origin->toString());
  ForeignFetchEvent* fetchEvent = ForeignFetchEvent::create(
      workerGlobalScope()->scriptController()->getScriptState(),
      EventTypeNames::foreignfetch, eventInit, respondWithObserver,
      waitUntilObserver);
  waitUntilObserver->willDispatchEvent();
  respondWithObserver->willDispatchEvent();
  DispatchEventResult dispatchResult =
      workerGlobalScope()->dispatchEvent(fetchEvent);
  respondWithObserver->didDispatchEvent(dispatchResult);
  // false is okay because waitUntil for foreign fetch event doesn't care
  // about the promise rejection or an uncaught runtime script error.
  waitUntilObserver->didDispatchEvent(false /* errorOccurred */);
}
Example #9
0
TEST_F(SecurityOriginTest, CreateFromTuple) {
  struct TestCase {
    const char* scheme;
    const char* host;
    unsigned short port;
    const char* origin;
  } cases[] = {
      {"http", "example.com", 80, "http://example.com"},
      {"http", "example.com", 81, "http://example.com:81"},
      {"https", "example.com", 443, "https://example.com"},
      {"https", "example.com", 444, "https://example.com:444"},
      {"file", "", 0, "file://"},
      {"file", "example.com", 0, "file://"},
  };

  for (const auto& test : cases) {
    RefPtr<SecurityOrigin> origin =
        SecurityOrigin::create(test.scheme, test.host, test.port);
    EXPECT_EQ(test.origin, origin->toString()) << test.origin;
  }
}
Example #10
0
String HTMLAnchorElement::origin() const
{
    RefPtr<SecurityOrigin> origin = SecurityOrigin::create(href());
    return origin->toString();
}
void CookieDatabaseBackingStore::invokeSendChangesToDatabase()
{
    ASSERT(isCurrentThread());

    if (!m_db.isOpen()) {
        LOG_ERROR("Timer Fired, but database is closed.");
        return;
    }

    Vector<CookieAction> changedCookies;
    {
        MutexLocker lock(m_mutex);
        changedCookies.swap(m_changedCookies);
        ASSERT(m_changedCookies.isEmpty());
    }

    if (changedCookies.isEmpty()) {
        CookieLog("CookieBackingStore - Timer fired, but no cookies in changelist");
        return;
    }
    CookieLog("CookieBackingStore - Timer fired, sending changes to database. We have %d changes", changedCookies.size());
    SQLiteTransaction transaction(m_db, false);
    transaction.begin();

    // Iterate through every element in the change list to make calls
    // If error occurs, ignore it and continue to the next statement
    size_t sizeOfChange = changedCookies.size();
    for (size_t i = 0; i < sizeOfChange; i++) {
        SQLiteStatement* m_statement;
        const RefPtr<ParsedCookie> cookie = changedCookies[i].first;
        UpdateParameter action = changedCookies[i].second;

        if (action == Delete) {
            m_statement = m_deleteStatement;
            CookieLog("CookieBackingStore - deleting cookie %s.", cookie.toString().utf8().data());

            // Binds all the values
            if (m_statement->bindText(1, cookie->name()) || m_statement->bindText(2, cookie->domain())
                || m_statement->bindText(3, cookie->path()) || m_statement->bindText(4, cookie->protocol())) {
                LOG_ERROR("Cannot bind cookie data to delete");
                LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
                ASSERT_NOT_REACHED();
                continue;
            }
        } else {
            if (action == Update) {
                CookieLog("CookieBackingStore - updating cookie %s.", cookie->toString().utf8().data());
                m_statement = m_updateStatement;
            } else {
                CookieLog("CookieBackingStore - inserting cookie %s.", cookie->toString().utf8().data());
                m_statement = m_insertStatement;
            }

            // Binds all the values
            if (m_statement->bindText(1, cookie->name()) || m_statement->bindText(2, cookie->value())
                || m_statement->bindText(3, cookie->domain()) || m_statement->bindText(4, cookie->path())
                || m_statement->bindDouble(5, cookie->expiry()) || m_statement->bindDouble(6, cookie->lastAccessed())
                || m_statement->bindInt64(7, cookie->isSecure()) || m_statement->bindInt64(8, cookie->isHttpOnly())
                || m_statement->bindDouble(9, cookie->creationTime()) || m_statement->bindText(10, cookie->protocol())) {
                LOG_ERROR("Cannot bind cookie data to save");
                LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
                ASSERT_NOT_REACHED();
                continue;
            }
        }

        int rc = m_statement->step();
        m_statement->reset();
        if (rc != SQLResultOk && rc != SQLResultDone) {
            LOG_ERROR("Cannot make call to the database");
            LOG_ERROR("SQLite Error Message: %s", m_db.lastErrorMsg());
            ASSERT_NOT_REACHED();
            continue;
        }
    }
    transaction.commit();
    CookieLog("CookieBackingStore - transaction complete");
}
static bool timingFunctionRoundTrips(const String& string)
{
    RefPtr<TimingFunction> timingFunction = AnimationInputHelpers::parseTimingFunction(string);
    return timingFunction && string == timingFunction->toString();
}
 void timingFunctionRoundTrips(const String& string, ExceptionState& exceptionState)
 {
     RefPtr<TimingFunction> timingFunction = parseTimingFunction(string, exceptionState);
     EXPECT_NE(nullptr, timingFunction);
     EXPECT_EQ(string, timingFunction->toString());
 }
Example #14
0
void CookieManager::addCookieToMap(CookieMap* targetMap, PassRefPtr<ParsedCookie> prpCandidateCookie, BackingStoreRemovalPolicy postToBackingStore, CookieFilter filter)
{
    RefPtr<ParsedCookie> replacedCookie = 0;
    RefPtr<ParsedCookie> candidateCookie = prpCandidateCookie;

    if (!targetMap->addOrReplaceCookie(candidateCookie, replacedCookie, filter)) {
        CookieLog("CookieManager - rejecting new cookie - %s.\n", candidateCookie->toString().utf8().data());
        return;
    }

    if (replacedCookie) {
        CookieLog("CookieManager - updating new cookie - %s.\n", candidateCookie->toString().utf8().data());

        // A cookie was replaced in targetMap.
        // If old cookie is non-session and new one is, we have to delete it from backingstore
        // If new cookie is non-session and old one is, we have to add it to backingstore
        // If both sessions are non-session, then we update it in the backingstore
        bool newIsSession = candidateCookie->isSession();
        bool oldIsSession = replacedCookie->isSession();

        if (postToBackingStore == RemoveFromBackingStore) {
            if (!newIsSession && !oldIsSession)
                m_cookieBackingStore->update(candidateCookie);
            else if (newIsSession && !oldIsSession) {
                // Must manually decrease the counter because it was not counted when
                // the cookie was removed in cookieVector.
                removedCookie();
                m_cookieBackingStore->remove(replacedCookie);
            } else if (!newIsSession && oldIsSession) {
                // Must manually increase the counter because it was not counted when
                // the cookie was added in cookieVector.
                addedCookie();
                m_cookieBackingStore->insert(candidateCookie);
            }
        }
        return;
    }

    CookieLog("CookieManager - adding new cookie - %s.\n", candidateCookie->toString().utf8().data());

    RefPtr<ParsedCookie> oldestCookie = 0;
    // Check if we have not reached the per cookie domain limit.
    // If that is not true, we check if the global limit has been reached if backingstore mode is on
    // Two points:
    // 1) We only do a global check if backingstore mode is on because the global cookie limit only
    //    counts session cookies that are saved in the database. If the user goes over the limit
    //    when they are in private mode, we know that the total cookie limit will be under the limit
    //    once the user goes back to normal mode (memory deleted and reloaded from the database)
    // 2) We use else if for this statement because if we remove a cookie in the 1st statement
    //    then it means the global count will never exceed the limit

    CookieLimitLog("CookieManager - local count: %d  global count: %d", targetMap->count(), m_count);
    if (targetMap->count() > s_maxCookieCountPerHost) {
        CookieLog("CookieManager - deleting oldest cookie from this map due to domain count.\n");
        oldestCookie = targetMap->removeOldestCookie();
    } else if (m_count > s_globalMaxCookieCount && (postToBackingStore != DoNotRemoveFromBackingStore)) {
        CookieLimitLog("CookieManager - Global limit reached, initiate cookie limit clean up.");
        initiateCookieLimitCleanUp();
    }

    // Only add non session cookie to the backing store.
    if (postToBackingStore == RemoveFromBackingStore) {
        if (oldestCookie && !oldestCookie->isSession()) {
            CookieLog("CookieManager - oldestCookie exists, deleting it from backingstore and destructing.\n");
            m_cookieBackingStore->remove(oldestCookie);
        }
        if (!candidateCookie->isSession())
            m_cookieBackingStore->insert(candidateCookie);
    }
}
Example #15
0
void CookieManager::getRawCookies(Vector<RefPtr<ParsedCookie> > &stackOfCookies, const KURL& requestURL, CookieFilter filter) const
{
    // Force a sync load of the database
    if (!m_syncedWithDatabase && !m_privateMode)
        m_cookieBackingStore->openAndLoadDatabaseSynchronously(cookieJar());

    CookieLog("CookieManager - getRawCookies - processing url with domain - %s & protocol: %s & path: %s\n", requestURL.host().utf8().data(), requestURL.protocol().utf8().data(), requestURL.path().utf8().data());

    const bool invalidScheme = shouldIgnoreScheme(requestURL.protocol());
    const bool specialCaseForWebWorks = invalidScheme && m_shouldDumpAllCookies;
    const bool isConnectionSecure = requestURL.protocolIs("https") || requestURL.protocolIs("wss") || specialCaseForWebWorks;

    Vector<RefPtr<ParsedCookie> > cookieCandidates;
    Vector<CookieMap*> protocolsToSearch;

    // Special Case: If a server sets a "secure" cookie over a non-secure channel and tries to access the cookie
    // over a secure channel, it will not succeed because the secure protocol isn't mapped to the insecure protocol yet.
    // Set the map to the non-secure version, so it'll search the mapping for a secure cookie.
    CookieMap* targetMap = m_managerMap.get(requestURL.protocol());
    if (!targetMap && isConnectionSecure) {
        CookieLog("CookieManager - special case: secure protocol are not linked yet.");
        if (requestURL.protocolIs("https"))
            targetMap = m_managerMap.get("http");
        else if (requestURL.protocolIs("wss"))
            targetMap = m_managerMap.get("ws");
    }

    // Decide which scheme tree we should look at.
    // Return on invalid schemes. cookies are currently disabled on file and local.
    // We only want to enable them for WebWorks that enabled a special flag.
    if (specialCaseForWebWorks)
        copyValuesToVector(m_managerMap, protocolsToSearch);
    else if (invalidScheme)
        return;
    else {
        protocolsToSearch.append(targetMap);
        // FIXME: this is a hack for webworks apps; RFC 6265 says "Cookies do not provide isolation by scheme"
        // so we should not be checking protocols at all. See PR 135595
        if (m_shouldDumpAllCookies) {
            protocolsToSearch.append(m_managerMap.get("file"));
            protocolsToSearch.append(m_managerMap.get("local"));
        }
    }

    Vector<String> delimitedHost;

    // IP addresses are stored in a particular format (due to ipv6). Reduce the ip address so we can match
    // it with the one in memory.
    BlackBerry::Platform::String canonicalIP = BlackBerry::Platform::getCanonicalIPFormat(requestURL.host());
    if (!canonicalIP.empty())
        delimitedHost.append(String(canonicalIP.c_str()));
    else
        requestURL.host().lower().split(".", true, delimitedHost);

    // Go through all the protocol trees that we need to search for
    // and get all cookies that are valid for this domain
    for (size_t k = 0; k < protocolsToSearch.size(); k++) {
        CookieMap* currentMap = protocolsToSearch[k];

        // if no cookies exist for this protocol, break right away
        if (!currentMap)
            continue;

        CookieLog("CookieManager - looking at protocol map %s \n", currentMap->getName().utf8().data());

        // Special case for local and files - because WebApps expect to get ALL cookies from the backing-store on local protocol
        if (specialCaseForWebWorks) {
            CookieLog("CookieManager - special case find in protocol map - %s\n", currentMap->getName().utf8().data());
            currentMap->getAllChildCookies(&cookieCandidates);
        } else {
            // Get cookies from the null domain map
            currentMap->getAllCookies(&cookieCandidates);

            // Get cookies from Host-only cookies
            if (canonicalIP.empty()) {
                CookieLog("CookieManager - looking for host-only cookies for host - %s", requestURL.host().utf8().data());
                CookieMap* hostMap = currentMap->getSubdomainMap(requestURL.host());
                if (hostMap)
                    hostMap->getAllCookies(&cookieCandidates);
            }

            // Get cookies from the valid domain maps
            int i = delimitedHost.size() - 1;
            while (i >= 0) {
                CookieLog("CookieManager - finding %s in currentmap\n", delimitedHost[i].utf8().data());
                currentMap = currentMap->getSubdomainMap(delimitedHost[i]);
                // if this subdomain/domain does not exist in our mapping then we simply exit
                if (!currentMap) {
                    CookieLog("CookieManager - cannot find next map exiting the while loop.\n");
                    break;
                }
                CookieLog("CookieManager - found the map, grabbing cookies from this map\n");
                currentMap->getAllCookies(&cookieCandidates);
                i--;
            }
        }
    }

    CookieLog("CookieManager - there are %d cookies in candidate\n", cookieCandidates.size());

    for (size_t i = 0; i < cookieCandidates.size(); ++i) {
        RefPtr<ParsedCookie> cookie = cookieCandidates[i];

        // According to the path-matches rules in RFC6265, section 5.1.4,
        // we should add a '/' at the end of cookie-path for comparison if the cookie-path is not end with '/'.
        String path = cookie->path();
        CookieLog("CookieManager - comparing cookie path %s (len %d) to request path %s (len %d)", path.utf8().data(), path.length(), requestURL.path().utf8().data(), path.length());
        if (!equalIgnoringCase(path, requestURL.path()) && !path.endsWith("/", false))
            path = path + "/";

        // Only secure connections have access to secure cookies. Unless specialCaseForWebWorks is true.
        // Get the cookies filtering out HttpOnly cookies if requested.
        if (requestURL.path().startsWith(path, false) && (isConnectionSecure || !cookie->isSecure()) && (filter == WithHttpOnlyCookies || !cookie->isHttpOnly())) {
            CookieLog("CookieManager - cookie chosen - %s\n", cookie->toString().utf8().data());
            cookie->setLastAccessed(currentTime());
            stackOfCookies.append(cookie);
        }
    }

    std::stable_sort(stackOfCookies.begin(), stackOfCookies.end(), cookieSorter);
}