• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/child/web_database_observer_impl.h"
6 
7 #include "base/metrics/histogram.h"
8 #include "base/strings/string16.h"
9 #include "content/common/database_messages.h"
10 #include "third_party/WebKit/public/platform/WebCString.h"
11 #include "third_party/WebKit/public/platform/WebString.h"
12 #include "third_party/sqlite/sqlite3.h"
13 
14 using blink::WebString;
15 
16 namespace content {
17 
18 namespace {
19 
20 const int kResultHistogramSize = 50;
21 const int kCallsiteHistogramSize = 10;
22 
DetermineHistogramResult(int websql_error,int sqlite_error)23 int DetermineHistogramResult(int websql_error, int sqlite_error) {
24   // If we have a sqlite error, log it after trimming the extended bits.
25   // There are 26 possible values, but we leave room for some new ones.
26   if (sqlite_error)
27     return std::min(sqlite_error & 0xff, 30);
28 
29   // Otherwise, websql_error may be an SQLExceptionCode, SQLErrorCode
30   // or a DOMExceptionCode, or -1 for success.
31   if (websql_error == -1)
32     return 0;  // no error
33 
34   // SQLExceptionCode starts at 1000
35   if (websql_error >= 1000)
36     websql_error -= 1000;
37 
38   return std::min(websql_error + 30, kResultHistogramSize - 1);
39 }
40 
41 #define HISTOGRAM_WEBSQL_RESULT(name, is_sync_database, \
42                                 callsite, websql_error, sqlite_error) \
43   do { \
44     DCHECK(callsite < kCallsiteHistogramSize); \
45     int result = DetermineHistogramResult(websql_error, sqlite_error); \
46     if (is_sync_database) { \
47       UMA_HISTOGRAM_ENUMERATION("websql.Sync." name, \
48                                 result, kResultHistogramSize); \
49       if (result) { \
50         UMA_HISTOGRAM_ENUMERATION("websql.Sync." name ".ErrorSite", \
51                                   callsite, kCallsiteHistogramSize); \
52       } \
53     } else { \
54       UMA_HISTOGRAM_ENUMERATION("websql.Async." name, \
55                                 result, kResultHistogramSize); \
56       if (result) { \
57         UMA_HISTOGRAM_ENUMERATION("websql.Async." name ".ErrorSite", \
58                                   callsite, kCallsiteHistogramSize); \
59       } \
60     } \
61   } while (0)
62 
63 }  // namespace
64 
WebDatabaseObserverImpl(IPC::SyncMessageFilter * sender)65 WebDatabaseObserverImpl::WebDatabaseObserverImpl(
66     IPC::SyncMessageFilter* sender)
67     : sender_(sender),
68       open_connections_(new webkit_database::DatabaseConnectionsWrapper) {
69   DCHECK(sender);
70 }
71 
~WebDatabaseObserverImpl()72 WebDatabaseObserverImpl::~WebDatabaseObserverImpl() {
73 }
74 
databaseOpened(const WebString & origin_identifier,const WebString & database_name,const WebString & database_display_name,unsigned long estimated_size)75 void WebDatabaseObserverImpl::databaseOpened(
76     const WebString& origin_identifier,
77     const WebString& database_name,
78     const WebString& database_display_name,
79     unsigned long estimated_size) {
80   open_connections_->AddOpenConnection(origin_identifier.utf8(),
81                                        database_name);
82   sender_->Send(new DatabaseHostMsg_Opened(
83       origin_identifier.utf8(), database_name,
84       database_display_name, estimated_size));
85 }
86 
databaseModified(const WebString & origin_identifier,const WebString & database_name)87 void WebDatabaseObserverImpl::databaseModified(
88     const WebString& origin_identifier,
89     const WebString& database_name) {
90   sender_->Send(new DatabaseHostMsg_Modified(
91       origin_identifier.utf8(), database_name));
92 }
93 
databaseClosed(const WebString & origin_identifier,const WebString & database_name)94 void WebDatabaseObserverImpl::databaseClosed(
95     const WebString& origin_identifier,
96     const WebString& database_name) {
97   sender_->Send(new DatabaseHostMsg_Closed(
98       origin_identifier.utf8(), database_name));
99   open_connections_->RemoveOpenConnection(origin_identifier.utf8(),
100                                           database_name);
101 }
102 
reportOpenDatabaseResult(const WebString & origin_identifier,const WebString & database_name,bool is_sync_database,int callsite,int websql_error,int sqlite_error)103 void WebDatabaseObserverImpl::reportOpenDatabaseResult(
104     const WebString& origin_identifier,
105     const WebString& database_name,
106     bool is_sync_database,
107     int callsite, int websql_error, int sqlite_error) {
108   HISTOGRAM_WEBSQL_RESULT("OpenResult", is_sync_database,
109                           callsite, websql_error, sqlite_error);
110   HandleSqliteError(origin_identifier, database_name, sqlite_error);
111 }
112 
reportChangeVersionResult(const WebString & origin_identifier,const WebString & database_name,bool is_sync_database,int callsite,int websql_error,int sqlite_error)113 void WebDatabaseObserverImpl::reportChangeVersionResult(
114     const WebString& origin_identifier,
115     const WebString& database_name,
116     bool is_sync_database,
117     int callsite, int websql_error, int sqlite_error) {
118   HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", is_sync_database,
119                           callsite, websql_error, sqlite_error);
120   HandleSqliteError(origin_identifier, database_name, sqlite_error);
121 }
122 
reportStartTransactionResult(const WebString & origin_identifier,const WebString & database_name,bool is_sync_database,int callsite,int websql_error,int sqlite_error)123 void WebDatabaseObserverImpl::reportStartTransactionResult(
124     const WebString& origin_identifier,
125     const WebString& database_name,
126     bool is_sync_database,
127     int callsite, int websql_error, int sqlite_error) {
128   HISTOGRAM_WEBSQL_RESULT("BeginResult", is_sync_database,
129                           callsite, websql_error, sqlite_error);
130   HandleSqliteError(origin_identifier, database_name, sqlite_error);
131 }
132 
reportCommitTransactionResult(const WebString & origin_identifier,const WebString & database_name,bool is_sync_database,int callsite,int websql_error,int sqlite_error)133 void WebDatabaseObserverImpl::reportCommitTransactionResult(
134     const WebString& origin_identifier,
135     const WebString& database_name,
136     bool is_sync_database,
137     int callsite, int websql_error, int sqlite_error) {
138   HISTOGRAM_WEBSQL_RESULT("CommitResult", is_sync_database,
139                           callsite, websql_error, sqlite_error);
140   HandleSqliteError(origin_identifier, database_name, sqlite_error);
141 }
142 
reportExecuteStatementResult(const WebString & origin_identifier,const WebString & database_name,bool is_sync_database,int callsite,int websql_error,int sqlite_error)143 void WebDatabaseObserverImpl::reportExecuteStatementResult(
144     const WebString& origin_identifier,
145     const WebString& database_name,
146     bool is_sync_database,
147     int callsite, int websql_error, int sqlite_error) {
148   HISTOGRAM_WEBSQL_RESULT("StatementResult", is_sync_database,
149                           callsite, websql_error, sqlite_error);
150   HandleSqliteError(origin_identifier, database_name, sqlite_error);
151 }
152 
reportVacuumDatabaseResult(const WebString & origin_identifier,const WebString & database_name,bool is_sync_database,int sqlite_error)153 void WebDatabaseObserverImpl::reportVacuumDatabaseResult(
154     const WebString& origin_identifier,
155     const WebString& database_name,
156     bool is_sync_database,
157     int sqlite_error) {
158   int result = DetermineHistogramResult(-1, sqlite_error);
159   if (is_sync_database) {
160     UMA_HISTOGRAM_ENUMERATION("websql.Sync.VacuumResult",
161                               result, kResultHistogramSize);
162   } else {
163     UMA_HISTOGRAM_ENUMERATION("websql.Async.VacuumResult",
164                               result, kResultHistogramSize);
165   }
166   HandleSqliteError(origin_identifier, database_name, sqlite_error);
167 }
168 
WaitForAllDatabasesToClose()169 void WebDatabaseObserverImpl::WaitForAllDatabasesToClose() {
170   open_connections_->WaitForAllDatabasesToClose();
171 }
172 
HandleSqliteError(const WebString & origin_identifier,const WebString & database_name,int error)173 void WebDatabaseObserverImpl::HandleSqliteError(
174     const WebString& origin_identifier,
175     const WebString& database_name,
176     int error) {
177   // We filter out errors which the backend doesn't act on to avoid
178   // a unnecessary ipc traffic, this method can get called at a fairly
179   // high frequency (per-sqlstatement).
180   if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) {
181     sender_->Send(new DatabaseHostMsg_HandleSqliteError(
182         origin_identifier.utf8(),
183         database_name,
184         error));
185   }
186 }
187 
188 }  // namespace content
189