summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/service_worker/service_worker_database.cc335
-rw-r--r--content/browser/service_worker/service_worker_database.h16
-rw-r--r--content/browser/service_worker/service_worker_storage.cc2
-rw-r--r--tools/metrics/histograms/histograms.xml30
4 files changed, 265 insertions, 118 deletions
diff --git a/content/browser/service_worker/service_worker_database.cc b/content/browser/service_worker/service_worker_database.cc
index 73c4a31..f4da827 100644
--- a/content/browser/service_worker/service_worker_database.cc
+++ b/content/browser/service_worker/service_worker_database.cc
@@ -9,6 +9,7 @@
#include "base/file_util.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -77,6 +78,14 @@ const char kPurgeableResIdKeyPrefix[] = "PRES:";
const int64 kCurrentSchemaVersion = 1;
+// For histogram.
+const char kOpenResultHistogramLabel[] =
+ "ServiceWorker.Database.OpenResult";
+const char kReadResultHistogramLabel[] =
+ "ServiceWorker.Database.ReadResult";
+const char kWriteResultHistogramLabel[] =
+ "ServiceWorker.Database.WriteResult";
+
bool RemovePrefix(const std::string& str,
const std::string& prefix,
std::string* out) {
@@ -169,19 +178,51 @@ void PutPurgeableResourceIdToBatch(int64 resource_id,
batch->Put(CreateResourceIdKey(kPurgeableResIdKeyPrefix, resource_id), "");
}
-bool ParseRegistrationData(const std::string& serialized,
- ServiceWorkerDatabase::RegistrationData* out) {
+ServiceWorkerDatabase::Status ParseId(
+ const std::string& serialized,
+ int64* out) {
+ DCHECK(out);
+ int64 id;
+ if (!base::StringToInt64(serialized, &id) || id < 0)
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
+ *out = id;
+ return ServiceWorkerDatabase::STATUS_OK;
+}
+
+ServiceWorkerDatabase::Status ParseDatabaseVersion(
+ const std::string& serialized,
+ int64* out) {
+ DCHECK(out);
+ const int kFirstValidVersion = 1;
+ int64 version;
+ if (!base::StringToInt64(serialized, &version) ||
+ version < kFirstValidVersion) {
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
+ }
+ if (kCurrentSchemaVersion < version) {
+ DLOG(ERROR) << "ServiceWorkerDatabase has newer schema version"
+ << " than the current latest version: "
+ << version << " vs " << kCurrentSchemaVersion;
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
+ }
+ *out = version;
+ return ServiceWorkerDatabase::STATUS_OK;
+}
+
+ServiceWorkerDatabase::Status ParseRegistrationData(
+ const std::string& serialized,
+ ServiceWorkerDatabase::RegistrationData* out) {
DCHECK(out);
ServiceWorkerRegistrationData data;
if (!data.ParseFromString(serialized))
- return false;
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
GURL scope_url(data.scope_url());
GURL script_url(data.script_url());
if (!scope_url.is_valid() ||
!script_url.is_valid() ||
scope_url.GetOrigin() != script_url.GetOrigin()) {
- return false;
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
}
// Convert ServiceWorkerRegistrationData to RegistrationData.
@@ -193,24 +234,25 @@ bool ParseRegistrationData(const std::string& serialized,
out->has_fetch_handler = data.has_fetch_handler();
out->last_update_check =
base::Time::FromInternalValue(data.last_update_check_time());
- return true;
+ return ServiceWorkerDatabase::STATUS_OK;
}
-bool ParseResourceRecord(const std::string& serialized,
- ServiceWorkerDatabase::ResourceRecord* out) {
+ServiceWorkerDatabase::Status ParseResourceRecord(
+ const std::string& serialized,
+ ServiceWorkerDatabase::ResourceRecord* out) {
DCHECK(out);
ServiceWorkerResourceRecord record;
if (!record.ParseFromString(serialized))
- return false;
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
GURL url(record.url());
if (!url.is_valid())
- return false;
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
// Convert ServiceWorkerResourceRecord to ResourceRecord.
out->resource_id = record.resource_id();
out->url = url;
- return true;
+ return ServiceWorkerDatabase::STATUS_OK;
}
ServiceWorkerDatabase::Status LevelDBStatusToStatus(
@@ -219,12 +261,34 @@ ServiceWorkerDatabase::Status LevelDBStatusToStatus(
return ServiceWorkerDatabase::STATUS_OK;
else if (status.IsNotFound())
return ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND;
+ else if (status.IsIOError())
+ return ServiceWorkerDatabase::STATUS_ERROR_IO_ERROR;
else if (status.IsCorruption())
return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
else
return ServiceWorkerDatabase::STATUS_ERROR_FAILED;
}
+const char* StatusToString(ServiceWorkerDatabase::Status status) {
+ switch (status) {
+ case ServiceWorkerDatabase::STATUS_OK:
+ return "Database OK";
+ case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND:
+ return "Database not found";
+ case ServiceWorkerDatabase::STATUS_ERROR_IO_ERROR:
+ return "Database IO error";
+ case ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED:
+ return "Database corrupted";
+ case ServiceWorkerDatabase::STATUS_ERROR_FAILED:
+ return "Database operation failed";
+ case ServiceWorkerDatabase::STATUS_ERROR_MAX:
+ NOTREACHED();
+ return "Database unknown error";
+ }
+ NOTREACHED();
+ return "Database unknown error";
+}
+
} // namespace
ServiceWorkerDatabase::RegistrationData::RegistrationData()
@@ -299,10 +363,11 @@ ServiceWorkerDatabase::GetOriginsWithRegistrations(std::set<GURL>* origins) {
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) {
- if (!itr->status().ok()) {
- HandleError(FROM_HERE, itr->status());
+ status = LevelDBStatusToStatus(itr->status());
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
origins->clear();
- return LevelDBStatusToStatus(itr->status());
+ return status;
}
std::string origin;
@@ -310,7 +375,9 @@ ServiceWorkerDatabase::GetOriginsWithRegistrations(std::set<GURL>* origins) {
break;
origins->insert(GURL(origin));
}
- return STATUS_OK;
+
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin(
@@ -331,24 +398,28 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin(
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
- if (!itr->status().ok()) {
- HandleError(FROM_HERE, itr->status());
+ status = LevelDBStatusToStatus(itr->status());
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
registrations->clear();
- return LevelDBStatusToStatus(itr->status());
+ return status;
}
if (!RemovePrefix(itr->key().ToString(), prefix, NULL))
break;
RegistrationData registration;
- if (!ParseRegistrationData(itr->value().ToString(), &registration)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
+ status = ParseRegistrationData(itr->value().ToString(), &registration);
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
registrations->clear();
- return STATUS_ERROR_CORRUPTED;
+ return status;
}
registrations->push_back(registration);
}
- return STATUS_OK;
+
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations(
@@ -364,24 +435,28 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations(
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) {
- if (!itr->status().ok()) {
- HandleError(FROM_HERE, itr->status());
+ status = LevelDBStatusToStatus(itr->status());
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
registrations->clear();
- return LevelDBStatusToStatus(itr->status());
+ return status;
}
if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL))
break;
RegistrationData registration;
- if (!ParseRegistrationData(itr->value().ToString(), &registration)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
+ status = ParseRegistrationData(itr->value().ToString(), &registration);
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
registrations->clear();
- return STATUS_ERROR_CORRUPTED;
+ return status;
}
registrations->push_back(registration);
}
- return STATUS_OK;
+
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
@@ -675,18 +750,18 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
}
leveldb::DB* db = NULL;
- leveldb::Status db_status =
- leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db);
- if (!db_status.ok()) {
+ Status status = LevelDBStatusToStatus(
+ leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db));
+ HandleOpenResult(FROM_HERE, status);
+ if (status != STATUS_OK) {
DCHECK(!db);
// TODO(nhiroki): Should we retry to open the database?
- HandleError(FROM_HERE, db_status);
- return LevelDBStatusToStatus(db_status);
+ return status;
}
db_.reset(db);
int64 db_version;
- Status status = ReadDatabaseVersion(&db_version);
+ status = ReadDatabaseVersion(&db_version);
if (status != STATUS_OK)
return status;
DCHECK_LE(0, db_version);
@@ -711,26 +786,21 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId(
DCHECK(next_avail_id);
std::string value;
- leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value);
- if (status.IsNotFound()) {
+ Status status = LevelDBStatusToStatus(
+ db_->Get(leveldb::ReadOptions(), id_key, &value));
+ if (status == STATUS_ERROR_NOT_FOUND) {
// Nobody has gotten the next resource id for |id_key|.
*next_avail_id = 0;
+ HandleReadResult(FROM_HERE, STATUS_OK);
return STATUS_OK;
+ } else if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
- if (!status.ok()) {
- HandleError(FROM_HERE, status);
- return LevelDBStatusToStatus(status);
- }
-
- int64 parsed;
- if (!base::StringToInt64(value, &parsed)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
- return STATUS_ERROR_CORRUPTED;
- }
-
- *next_avail_id = parsed;
- return STATUS_OK;
+ status = ParseId(value, next_avail_id);
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationData(
@@ -739,52 +809,54 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationData(
RegistrationData* registration) {
DCHECK(registration);
- std::string key = CreateRegistrationKey(registration_id, origin);
-
+ const std::string key = CreateRegistrationKey(registration_id, origin);
std::string value;
- leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value);
- if (!status.ok()) {
- if (!status.IsNotFound())
- HandleError(FROM_HERE, status);
- return LevelDBStatusToStatus(status);
- }
-
- RegistrationData parsed;
- if (!ParseRegistrationData(value, &parsed)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
- return STATUS_ERROR_CORRUPTED;
+ Status status = LevelDBStatusToStatus(
+ db_->Get(leveldb::ReadOptions(), key, &value));
+ if (status != STATUS_OK) {
+ HandleReadResult(
+ FROM_HERE,
+ status == STATUS_ERROR_NOT_FOUND ? STATUS_OK : status);
+ return status;
}
- *registration = parsed;
- return STATUS_OK;
+ status = ParseRegistrationData(value, registration);
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords(
int64 version_id,
std::vector<ResourceRecord>* resources) {
- DCHECK(resources);
+ DCHECK(resources->empty());
+
+ Status status = STATUS_OK;
+ const std::string prefix = CreateResourceRecordKeyPrefix(version_id);
- std::string prefix = CreateResourceRecordKeyPrefix(version_id);
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
- if (!itr->status().ok()) {
- HandleError(FROM_HERE, itr->status());
+ Status status = LevelDBStatusToStatus(itr->status());
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
resources->clear();
- return LevelDBStatusToStatus(itr->status());
+ return status;
}
if (!RemovePrefix(itr->key().ToString(), prefix, NULL))
break;
ResourceRecord resource;
- if (!ParseResourceRecord(itr->value().ToString(), &resource)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
+ status = ParseResourceRecord(itr->value().ToString(), &resource);
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
resources->clear();
- return STATUS_ERROR_CORRUPTED;
+ return status;
}
resources->push_back(resource);
}
- return STATUS_OK;
+
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords(
@@ -793,23 +865,27 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords(
leveldb::WriteBatch* batch) {
DCHECK(batch);
- std::string prefix = CreateResourceRecordKeyPrefix(version_id);
+ Status status = STATUS_OK;
+ const std::string prefix = CreateResourceRecordKeyPrefix(version_id);
+
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
- if (!itr->status().ok()) {
- HandleError(FROM_HERE, itr->status());
- return LevelDBStatusToStatus(itr->status());
+ status = LevelDBStatusToStatus(itr->status());
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
- std::string key = itr->key().ToString();
+ const std::string key = itr->key().ToString();
std::string unprefixed;
if (!RemovePrefix(key, prefix, &unprefixed))
break;
int64 resource_id;
- if (!base::StringToInt64(unprefixed, &resource_id)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
- return STATUS_ERROR_CORRUPTED;
+ status = ParseId(unprefixed, &resource_id);
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
// Remove a resource record.
@@ -820,7 +896,9 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords(
PutPurgeableResourceIdToBatch(resource_id, batch);
newly_purgeable_resources->push_back(resource_id);
}
- return STATUS_OK;
+
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds(
@@ -838,10 +916,11 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds(
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) {
- if (!itr->status().ok()) {
- HandleError(FROM_HERE, itr->status());
+ status = LevelDBStatusToStatus(itr->status());
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
ids->clear();
- return LevelDBStatusToStatus(itr->status());
+ return status;
}
std::string unprefixed;
@@ -849,14 +928,17 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds(
break;
int64 resource_id;
- if (!base::StringToInt64(unprefixed, &resource_id)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
+ status = ParseId(unprefixed, &resource_id);
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
ids->clear();
- return STATUS_ERROR_CORRUPTED;
+ return status;
}
ids->insert(resource_id);
}
- return STATUS_OK;
+
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteResourceIds(
@@ -921,32 +1003,23 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceIdsInBatch(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion(
int64* db_version) {
std::string value;
- leveldb::Status status =
- db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value);
- if (status.IsNotFound()) {
+ Status status = LevelDBStatusToStatus(
+ db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value));
+ if (status == STATUS_ERROR_NOT_FOUND) {
// The database hasn't been initialized yet.
*db_version = 0;
+ HandleReadResult(FROM_HERE, STATUS_OK);
return STATUS_OK;
}
- if (!status.ok()) {
- HandleError(FROM_HERE, status);
- return LevelDBStatusToStatus(status);
- }
- int64 parsed;
- if (!base::StringToInt64(value, &parsed)) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
- return STATUS_ERROR_CORRUPTED;
- }
-
- const int kFirstValidVersion = 1;
- if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) {
- HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version"));
- return STATUS_ERROR_CORRUPTED;
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
- *db_version = parsed;
- return STATUS_OK;
+ status = ParseDatabaseVersion(value, db_version);
+ HandleReadResult(FROM_HERE, status);
+ return status;
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteBatch(
@@ -960,10 +1033,10 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteBatch(
state_ = INITIALIZED;
}
- leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch);
- if (!status.ok())
- HandleError(FROM_HERE, status);
- return LevelDBStatusToStatus(status);
+ Status status = LevelDBStatusToStatus(
+ db_->Write(leveldb::WriteOptions(), batch));
+ HandleWriteResult(FROM_HERE, status);
+ return status;
}
void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded(
@@ -988,14 +1061,44 @@ bool ServiceWorkerDatabase::IsOpen() {
return db_ != NULL;
}
-void ServiceWorkerDatabase::HandleError(
+void ServiceWorkerDatabase::Disable(
const tracked_objects::Location& from_here,
- const leveldb::Status& status) {
- // TODO(nhiroki): Add an UMA histogram.
+ Status status) {
DLOG(ERROR) << "Failed at: " << from_here.ToString()
- << " with error: " << status.ToString();
+ << " with error: " << StatusToString(status);
+ DLOG(ERROR) << "ServiceWorkerDatabase is disabled.";
state_ = DISABLED;
db_.reset();
}
+void ServiceWorkerDatabase::HandleOpenResult(
+ const tracked_objects::Location& from_here,
+ Status status) {
+ if (status != ServiceWorkerDatabase::STATUS_OK)
+ Disable(from_here, status);
+ UMA_HISTOGRAM_ENUMERATION(kOpenResultHistogramLabel,
+ status,
+ ServiceWorkerDatabase::STATUS_ERROR_MAX);
+}
+
+void ServiceWorkerDatabase::HandleReadResult(
+ const tracked_objects::Location& from_here,
+ Status status) {
+ if (status != ServiceWorkerDatabase::STATUS_OK)
+ Disable(from_here, status);
+ UMA_HISTOGRAM_ENUMERATION(kReadResultHistogramLabel,
+ status,
+ ServiceWorkerDatabase::STATUS_ERROR_MAX);
+}
+
+void ServiceWorkerDatabase::HandleWriteResult(
+ const tracked_objects::Location& from_here,
+ Status status) {
+ if (status != ServiceWorkerDatabase::STATUS_OK)
+ Disable(from_here, status);
+ UMA_HISTOGRAM_ENUMERATION(kWriteResultHistogramLabel,
+ status,
+ ServiceWorkerDatabase::STATUS_ERROR_MAX);
+}
+
} // namespace content
diff --git a/content/browser/service_worker/service_worker_database.h b/content/browser/service_worker/service_worker_database.h
index 660b4c7..7b2a68d 100644
--- a/content/browser/service_worker/service_worker_database.h
+++ b/content/browser/service_worker/service_worker_database.h
@@ -39,11 +39,14 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
explicit ServiceWorkerDatabase(const base::FilePath& path);
~ServiceWorkerDatabase();
+ // Used in UMA. A new value must be appended only.
enum Status {
STATUS_OK,
STATUS_ERROR_NOT_FOUND,
+ STATUS_ERROR_IO_ERROR,
STATUS_ERROR_CORRUPTED,
STATUS_ERROR_FAILED,
+ STATUS_ERROR_MAX,
};
struct CONTENT_EXPORT RegistrationData {
@@ -273,9 +276,18 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
bool IsOpen();
- void HandleError(
+ void Disable(
const tracked_objects::Location& from_here,
- const leveldb::Status& status);
+ Status status);
+ void HandleOpenResult(
+ const tracked_objects::Location& from_here,
+ Status status);
+ void HandleReadResult(
+ const tracked_objects::Location& from_here,
+ Status status);
+ void HandleWriteResult(
+ const tracked_objects::Location& from_here,
+ Status status);
base::FilePath path_;
scoped_ptr<leveldb::Env> env_;
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 7ec25a4..0e40d94 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -64,6 +64,8 @@ ServiceWorkerStatusCode DatabaseStatusToStatusCode(
return SERVICE_WORKER_OK;
case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND:
return SERVICE_WORKER_ERROR_NOT_FOUND;
+ case ServiceWorkerDatabase::STATUS_ERROR_MAX:
+ NOTREACHED();
default:
return SERVICE_WORKER_ERROR_FAILED;
}
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c2fd7d3..3eece60 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -24517,6 +24517,28 @@ Therefore, the affected-histogram name has to have at least one dot in it.
</summary>
</histogram>
+<histogram name="ServiceWorker.Database.OpenResult"
+ enum="ServiceWorkerDatabaseStatus">
+ <owner>nhiroki@chromium.org</owner>
+ <summary>
+ Records result of opening a database for ServiceWorkerDatabase.
+ </summary>
+</histogram>
+
+<histogram name="ServiceWorker.Database.ReadResult"
+ enum="ServiceWorkerDatabaseStatus">
+ <owner>nhiroki@chromium.org</owner>
+ <summary>Records result of read operations in ServiceWorkerDatabase.</summary>
+</histogram>
+
+<histogram name="ServiceWorker.Database.WriteResult"
+ enum="ServiceWorkerDatabaseStatus">
+ <owner>nhiroki@chromium.org</owner>
+ <summary>
+ Records result of write operations in ServiceWorkerDatabase.
+ </summary>
+</histogram>
+
<histogram name="Settings.DefaultSearchProvider" enum="OmniboxSearchEngine">
<obsolete>
Deprecated in Chrome 30. Use Search.DefaultSearchProviderType instead.
@@ -42782,6 +42804,14 @@ Therefore, the affected-histogram name has to have at least one dot in it.
<int value="10" label="SERVICE_UTILITY_SEMANTIC_CAPS_FAILED"/>
</enum>
+<enum name="ServiceWorkerDatabaseStatus" type="int">
+ <int value="0" label="OK"/>
+ <int value="1" label="Not Found Error"/>
+ <int value="2" label="IO Error"/>
+ <int value="3" label="Corruption Error"/>
+ <int value="4" label="Operation Error"/>
+</enum>
+
<enum name="SessionStartupPref" type="int">
<int value="0" label="Open home page (unused)"/>
<int value="1" label="Continue from last opened pages"/>