cef/tests/unittests/storage_unittest.cc

475 lines
16 KiB
C++

// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "base/scoped_temp_dir.h"
#include "include/cef.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "test_handler.h"
#include "test_suite.h"
namespace {
static const char* kOrigin = "http://tests";
static const char* kNav1 = "http://tests/nav1.html";
static const char* kNav2 = "http://tests/nav2.html";
static const char* kKey1 = "foo";
static const char* kVal1 = "bar";
static const char* kKey2 = "choo";
static const char* kVal2 = "whatzit";
class StorageTestHandler : public TestHandler
{
public:
class V8Handler : public CefV8Handler
{
public:
V8Handler(CefRefPtr<StorageTestHandler> tester)
: tester_(tester) {}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE
{
if (arguments.size() != 2)
return false;
std::string key = arguments[0]->GetStringValue();
std::string val = arguments[1]->GetStringValue();
if (key == kKey1 && val == kVal1)
tester_->got_js_read1_.yes();
else if (key == kKey2 && val == kVal2)
tester_->got_js_read2_.yes();
return true;
}
CefRefPtr<StorageTestHandler> tester_;
IMPLEMENT_REFCOUNTING(V8Handler);
};
class StorageVisitor : public CefStorageVisitor
{
public:
enum Mode {
VisitKey,
DeleteKey1,
DeleteKey2
};
StorageVisitor(CefRefPtr<StorageTestHandler> tester,
const std::string& description, Mode mode,
TrackCallback* callback1, TrackCallback* callback2,
int expected_total)
: tester_(tester), description_(description), mode_(mode),
callback1_(callback1), callback2_(callback2),
expected_total_(expected_total), actual_total_(0)
{
}
virtual ~StorageVisitor()
{
EXPECT_EQ(expected_total_, actual_total_) << "test = "<< description_;
}
virtual bool Visit(CefStorageType type, const CefString& origin,
const CefString& key, const CefString& value, int count,
int total, bool& deleteData) OVERRIDE
{
EXPECT_EQ(type, tester_->type_);
std::string originStr = origin;
EXPECT_EQ(originStr, kOrigin);
std::string keyStr = key;
std::string valueStr = value;
if (keyStr == kKey1 && valueStr == kVal1)
callback1_->yes();
else if(keyStr == kKey2 && valueStr == kVal2)
callback2_->yes();
EXPECT_EQ(expected_total_, total) << "test = "<< description_;
if((mode_ == DeleteKey1 && keyStr == kKey1) ||
(mode_ == DeleteKey2 && keyStr == kKey2))
deleteData = true;
actual_total_++;
return true;
}
CefRefPtr<StorageTestHandler> tester_;
std::string description_;
Mode mode_;
TrackCallback* callback1_;
TrackCallback* callback2_;
int expected_total_;
int actual_total_;
IMPLEMENT_REFCOUNTING(StorageVisitor);
};
StorageTestHandler(CefStorageType type, bool expectKeysSet, bool leaveKeysSet)
: type_(type),
expect_keys_set_(expectKeysSet),
leave_keys_set_(leaveKeysSet),
nav_(0) {}
virtual void RunTest() OVERRIDE
{
// Verify the key status.
CefVisitStorage(type_, kOrigin, "",
new StorageVisitor(this, "startupvisit",
StorageVisitor::VisitKey,
&got_cpp_startupvisit_fail_,
&got_cpp_startupvisit_fail_,
expect_keys_set_?2:0));
std::stringstream ss;
std::string func = (type_==ST_LOCALSTORAGE?"localStorage":"sessionStorage");
// Values will be set vis JS on page load.
ss << "<html><head><script language=\"JavaScript\">" <<
func << ".setItem('" << std::string(kKey1) << "', '" <<
std::string(kVal1) << "');" <<
func << ".setItem('" << std::string(kKey2) << "', '" <<
std::string(kVal2) << "');"
"</script></head><body>Nav1</body></html>";
AddResource(kNav1, ss.str(), "text/html");
ss.str("");
// Values will be verified vis JS on page load.
ss << "<html><head><script language=\"JavaScript\">"
"window.test.result('" << std::string(kKey1) << "', " <<
func << ".getItem('" << std::string(kKey1) << "'));"
"window.test.result('" << std::string(kKey2) << "', " <<
func << ".getItem('" << std::string(kKey2) << "'));"
"</script></head><body>Nav2</body></html>";
AddResource(kNav2, ss.str(), "text/html");
ss.str("");
// Create the browser.
CreateBrowser(kNav1);
}
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE
{
if (nav_ == 0) {
// Verify read all.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "all_read",
StorageVisitor::VisitKey,
&got_cpp_all_read1_,
&got_cpp_all_read2_, 2));
// Verify read origin.
CefVisitStorage(type_, kOrigin, "",
new StorageVisitor(this, "origin_read",
StorageVisitor::VisitKey,
&got_cpp_origin_read1_,
&got_cpp_origin_read2_, 2));
// Verify read key1.
CefVisitStorage(type_, kOrigin, kKey1,
new StorageVisitor(this, "key1_read",
StorageVisitor::VisitKey,
&got_cpp_key_read1_,
&got_cpp_key_read1_fail_, 1));
// Verify read key2.
CefVisitStorage(type_, kOrigin, kKey2,
new StorageVisitor(this, "key2_read",
StorageVisitor::VisitKey,
&got_cpp_key_read2_fail_,
&got_cpp_key_read2_, 1));
// Delete key1. Verify that key2 still gets read.
CefVisitStorage(type_, kOrigin, "",
new StorageVisitor(this, "key1_delete",
StorageVisitor::DeleteKey1,
&got_cpp_key_delete1_delete_,
&got_cpp_key_delete1_, 2));
// Verify that key1 was deleted.
CefVisitStorage(type_, kOrigin, "",
new StorageVisitor(this, "key1_delete_verify",
StorageVisitor::VisitKey,
&got_cpp_afterdeletevisit1_fail_,
&got_cpp_afterdeletevisit1_, 1));
// Delete key2.
CefVisitStorage(type_, kOrigin, "",
new StorageVisitor(this, "key2_delete",
StorageVisitor::DeleteKey2,
&got_cpp_key_delete2_fail_,
&got_cpp_key_delete2_delete_, 1));
// Verify that all keys have been deleted.
CefVisitStorage(type_, kOrigin, "",
new StorageVisitor(this, "key2_delete_verify",
StorageVisitor::VisitKey,
&got_cpp_afterdeletevisit2_fail_,
&got_cpp_afterdeletevisit2_fail_, 0));
// Reset the values.
CefSetStorage(type_, kOrigin, kKey1, kVal1);
CefSetStorage(type_, kOrigin, kKey2, kVal2);
// Verify that all values have been reset.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "reset1a_verify",
StorageVisitor::VisitKey,
&got_cpp_all_reset1a_,
&got_cpp_all_reset2a_, 2));
// Delete all values.
CefDeleteStorage(type_, "", "");
// Verify that all values have been deleted.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "delete_all_verify",
StorageVisitor::VisitKey,
&got_cpp_afterdeleteall_fail_,
&got_cpp_afterdeleteall_fail_, 0));
// Reset all values.
CefSetStorage(type_, kOrigin, kKey1, kVal1);
CefSetStorage(type_, kOrigin, kKey2, kVal2);
// Verify that all values have been reset.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "reset1b_verify",
StorageVisitor::VisitKey,
&got_cpp_all_reset1b_,
&got_cpp_all_reset2b_, 2));
// Delete all values by origin.
CefDeleteStorage(type_, kOrigin, "");
// Verify that all values have been deleted.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "delete_origin_verify",
StorageVisitor::VisitKey,
&got_cpp_afterdeleteorigin_fail_,
&got_cpp_afterdeleteorigin_fail_, 0));
// Reset the values.
CefSetStorage(type_, kOrigin, kKey1, kVal1);
CefSetStorage(type_, kOrigin, kKey2, kVal2);
// Verify that all values have been reset.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "reset1c_verify",
StorageVisitor::VisitKey,
&got_cpp_all_reset1c_,
&got_cpp_all_reset2c_, 2));
// Delete key1.
CefDeleteStorage(type_, kOrigin, kKey1);
// Verify that key1 has been deleted.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "direct_key1_delete_verify",
StorageVisitor::VisitKey,
&got_cpp_afterdeletekey1_fail_,
&got_cpp_afterdeletekey1_, 1));
// Delete key2.
CefDeleteStorage(type_, kOrigin, kKey2);
// Verify that all values have been deleted.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "direct_key2_delete_verify",
StorageVisitor::VisitKey,
&got_cpp_afterdeletekey2_fail_,
&got_cpp_afterdeletekey2_fail_, 0));
// Reset all values.
CefSetStorage(type_, kOrigin, kKey1, kVal1);
CefSetStorage(type_, kOrigin, kKey2, kVal2);
// Verify that all values have been reset.
CefVisitStorage(type_, "", "",
new StorageVisitor(this, "reset1d_verify",
StorageVisitor::VisitKey,
&got_cpp_all_reset1d_,
&got_cpp_all_reset2d_, 2));
nav_++;
// Verify JS read after navigation.
frame->LoadURL(kNav2);
} else {
if (!leave_keys_set_) {
// Delete all values by origin.
CefDeleteStorage(type_, kOrigin, "");
}
// Verify the key status.
CefVisitStorage(type_, kOrigin, "",
new StorageVisitor(this, "shutdownvisit",
StorageVisitor::VisitKey,
&got_cpp_shutdownvisit_fail_,
&got_cpp_shutdownvisit_fail_,
leave_keys_set_?2:0));
DestroyTest();
}
}
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE
{
// Retrieve the 'window' object.
CefRefPtr<CefV8Value> object = context->GetGlobal();
CefRefPtr<CefV8Handler> handler = new V8Handler(this);
CefRefPtr<CefV8Value> testObj = CefV8Value::CreateObject(NULL, NULL);
testObj->SetValue("result", CefV8Value::CreateFunction("result", handler),
V8_PROPERTY_ATTRIBUTE_NONE);
object->SetValue("test", testObj, V8_PROPERTY_ATTRIBUTE_NONE);
}
CefStorageType type_;
bool expect_keys_set_;
bool leave_keys_set_;
int nav_;
TrackCallback got_cpp_startupvisit_fail_;
TrackCallback got_cpp_all_read1_;
TrackCallback got_cpp_all_read2_;
TrackCallback got_cpp_origin_read1_;
TrackCallback got_cpp_origin_read2_;
TrackCallback got_cpp_key_read1_;
TrackCallback got_cpp_key_read1_fail_;
TrackCallback got_cpp_key_read2_;
TrackCallback got_cpp_key_read2_fail_;
TrackCallback got_cpp_key_delete1_;
TrackCallback got_cpp_key_delete1_delete_;
TrackCallback got_cpp_key_delete2_delete_;
TrackCallback got_cpp_key_delete2_fail_;
TrackCallback got_cpp_afterdeletevisit1_;
TrackCallback got_cpp_afterdeletevisit1_fail_;
TrackCallback got_cpp_afterdeletevisit2_fail_;
TrackCallback got_cpp_all_reset1a_;
TrackCallback got_cpp_all_reset2a_;
TrackCallback got_cpp_afterdeleteall_fail_;
TrackCallback got_cpp_all_reset1b_;
TrackCallback got_cpp_all_reset2b_;
TrackCallback got_cpp_afterdeleteorigin_fail_;
TrackCallback got_cpp_all_reset1c_;
TrackCallback got_cpp_all_reset2c_;
TrackCallback got_cpp_afterdeletekey1_;
TrackCallback got_cpp_afterdeletekey1_fail_;
TrackCallback got_cpp_afterdeletekey2_fail_;
TrackCallback got_cpp_all_reset1d_;
TrackCallback got_cpp_all_reset2d_;
TrackCallback got_js_read1_;
TrackCallback got_js_read2_;
TrackCallback got_cpp_shutdownvisit_fail_;
};
void StorageTest(CefStorageType type, bool expectKeysSet, bool leaveKeysSet)
{
CefRefPtr<StorageTestHandler> handler =
new StorageTestHandler(type, expectKeysSet, leaveKeysSet);
handler->ExecuteTest();
if (expectKeysSet)
EXPECT_TRUE(handler->got_cpp_startupvisit_fail_);
else
EXPECT_FALSE(handler->got_cpp_startupvisit_fail_);
EXPECT_TRUE(handler->got_cpp_all_read1_);
EXPECT_TRUE(handler->got_cpp_all_read2_);
EXPECT_TRUE(handler->got_cpp_origin_read1_);
EXPECT_TRUE(handler->got_cpp_origin_read2_);
EXPECT_TRUE(handler->got_cpp_key_read1_);
EXPECT_FALSE(handler->got_cpp_key_read1_fail_);
EXPECT_TRUE(handler->got_cpp_key_read2_);
EXPECT_FALSE(handler->got_cpp_key_read2_fail_);
EXPECT_TRUE(handler->got_cpp_key_delete1_);
EXPECT_TRUE(handler->got_cpp_key_delete1_delete_);
EXPECT_TRUE(handler->got_cpp_key_delete2_delete_);
EXPECT_FALSE(handler->got_cpp_key_delete2_fail_);
EXPECT_TRUE(handler->got_cpp_afterdeletevisit1_);
EXPECT_FALSE(handler->got_cpp_afterdeletevisit1_fail_);
EXPECT_FALSE(handler->got_cpp_afterdeletevisit2_fail_);
EXPECT_TRUE(handler->got_cpp_all_reset1a_);
EXPECT_TRUE(handler->got_cpp_all_reset2a_);
EXPECT_FALSE(handler->got_cpp_afterdeleteall_fail_);
EXPECT_TRUE(handler->got_cpp_all_reset1b_);
EXPECT_TRUE(handler->got_cpp_all_reset2b_);
EXPECT_FALSE(handler->got_cpp_afterdeleteorigin_fail_);
EXPECT_TRUE(handler->got_cpp_all_reset1c_);
EXPECT_TRUE(handler->got_cpp_all_reset2c_);
EXPECT_TRUE(handler->got_cpp_afterdeletekey1_);
EXPECT_FALSE(handler->got_cpp_afterdeletekey1_fail_);
EXPECT_FALSE(handler->got_cpp_afterdeletekey2_fail_);
EXPECT_TRUE(handler->got_cpp_all_reset1d_);
EXPECT_TRUE(handler->got_cpp_all_reset2d_);
EXPECT_TRUE(handler->got_js_read1_);
EXPECT_TRUE(handler->got_js_read2_);
if (leaveKeysSet)
EXPECT_TRUE(handler->got_cpp_shutdownvisit_fail_);
else
EXPECT_FALSE(handler->got_cpp_shutdownvisit_fail_);
}
} // namespace
// Test localStorage.
TEST(StorageTest, Local)
{
StorageTest(ST_LOCALSTORAGE, false, false);
}
// Test sessionStorage.
TEST(StorageTest, Session)
{
StorageTest(ST_SESSIONSTORAGE, false, false);
}
// Test changing the localStorage directory.
TEST(StorageTest, LocalChangeDirectory)
{
std::string cache_path;
CefTestSuite::GetCachePath(cache_path);
ScopedTempDir temp_dir;
// Create a new temporary directory.
EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
// Set the new temporary directory as the storage location.
EXPECT_TRUE(CefSetStoragePath(ST_LOCALSTORAGE, temp_dir.path().value()));
// Run the test leaving behind the set keys.
StorageTest(ST_LOCALSTORAGE, false, true);
// Restore the original storage location.
EXPECT_TRUE(CefSetStoragePath(ST_LOCALSTORAGE, cache_path));
// Run the test. It will fail if the set keys exist in the original storage
// location.
StorageTest(ST_LOCALSTORAGE, false, false);
// Set the new temporary directory as the storage location.
EXPECT_TRUE(CefSetStoragePath(ST_LOCALSTORAGE, temp_dir.path().value()));
// Run the test verifying that the keys set previously still exist in the
// temporary directory.
StorageTest(ST_LOCALSTORAGE, true, false);
// Restore the original storage directory.
EXPECT_TRUE(CefSetStoragePath(ST_LOCALSTORAGE, cache_path));
}