1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/web_database_observer_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/database_messages.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebCString.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/sqlite/sqlite3.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebString;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kResultHistogramSize = 50;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCallsiteHistogramSize = 10;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DetermineHistogramResult(int websql_error, int sqlite_error) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have a sqlite error, log it after trimming the extended bits.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There are 26 possible values, but we leave room for some new ones.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sqlite_error)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::min(sqlite_error & 0xff, 30);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, websql_error may be an SQLExceptionCode, SQLErrorCode
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or a DOMExceptionCode, or -1 for success.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (websql_error == -1)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;  // no error
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SQLExceptionCode starts at 1000
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (websql_error >= 1000)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websql_error -= 1000;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::min(websql_error + 30, kResultHistogramSize - 1);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define UMA_HISTOGRAM_WEBSQL_RESULT(name, is_sync_database, \
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    callsite, websql_error, sqlite_error) \
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do { \
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(callsite < kCallsiteHistogramSize); \
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = DetermineHistogramResult(websql_error, sqlite_error); \
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (is_sync_database) { \
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("websql.Sync." name, \
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                result, kResultHistogramSize); \
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result) { \
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_ENUMERATION("websql.Sync." name ".ErrorSite", \
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  callsite, kCallsiteHistogramSize); \
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } \
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else { \
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("websql.Async." name, \
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                result, kResultHistogramSize); \
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result) { \
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UMA_HISTOGRAM_ENUMERATION("websql.Async." name ".ErrorSite", \
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  callsite, kCallsiteHistogramSize); \
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } \
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } \
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (0)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)WebDatabaseObserverImpl::WebDatabaseObserverImpl(IPC::SyncMessageFilter* sender)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : sender_(sender),
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      open_connections_(new storage::DatabaseConnectionsWrapper) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sender);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebDatabaseObserverImpl::~WebDatabaseObserverImpl() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::databaseOpened(
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_display_name,
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    unsigned long estimated_size) {
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  open_connections_->AddOpenConnection(origin_identifier.utf8(),
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       database_name);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sender_->Send(new DatabaseHostMsg_Opened(
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      origin_identifier.utf8(), database_name,
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      database_display_name, estimated_size));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::databaseModified(
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sender_->Send(new DatabaseHostMsg_Modified(
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      origin_identifier.utf8(), database_name));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::databaseClosed(
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sender_->Send(new DatabaseHostMsg_Closed(
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      origin_identifier.utf8(), database_name));
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  open_connections_->RemoveOpenConnection(origin_identifier.utf8(),
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                          database_name);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::reportOpenDatabaseResult(
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool is_sync_database,
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int callsite, int websql_error, int sqlite_error) {
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_WEBSQL_RESULT("OpenResult", is_sync_database, callsite,
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              websql_error, sqlite_error);
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HandleSqliteError(origin_identifier, database_name, sqlite_error);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::reportChangeVersionResult(
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool is_sync_database,
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int callsite, int websql_error, int sqlite_error) {
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", is_sync_database, callsite,
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              websql_error, sqlite_error);
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HandleSqliteError(origin_identifier, database_name, sqlite_error);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::reportStartTransactionResult(
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool is_sync_database,
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int callsite, int websql_error, int sqlite_error) {
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_WEBSQL_RESULT("BeginResult", is_sync_database, callsite,
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              websql_error, sqlite_error);
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HandleSqliteError(origin_identifier, database_name, sqlite_error);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::reportCommitTransactionResult(
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool is_sync_database,
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int callsite, int websql_error, int sqlite_error) {
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_WEBSQL_RESULT("CommitResult", is_sync_database, callsite,
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              websql_error, sqlite_error);
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HandleSqliteError(origin_identifier, database_name, sqlite_error);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::reportExecuteStatementResult(
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool is_sync_database,
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int callsite, int websql_error, int sqlite_error) {
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UMA_HISTOGRAM_WEBSQL_RESULT("StatementResult", is_sync_database, callsite,
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              websql_error, sqlite_error);
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HandleSqliteError(origin_identifier, database_name, sqlite_error);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::reportVacuumDatabaseResult(
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool is_sync_database,
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int sqlite_error) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = DetermineHistogramResult(-1, sqlite_error);
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (is_sync_database) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("websql.Sync.VacuumResult",
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              result, kResultHistogramSize);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("websql.Async.VacuumResult",
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              result, kResultHistogramSize);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HandleSqliteError(origin_identifier, database_name, sqlite_error);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::WaitForAllDatabasesToClose() {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  open_connections_->WaitForAllDatabasesToClose();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebDatabaseObserverImpl::HandleSqliteError(
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& origin_identifier,
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const WebString& database_name,
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int error) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We filter out errors which the backend doesn't act on to avoid
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a unnecessary ipc traffic, this method can get called at a fairly
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // high frequency (per-sqlstatement).
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sender_->Send(new DatabaseHostMsg_HandleSqliteError(
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        origin_identifier.utf8(),
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        database_name,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
188