sqlite_cursor.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 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#ifndef CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
6#define CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
7
8#include <jni.h>
9#include <vector>
10
11#include "base/android/scoped_java_ref.h"
12#include "base/basictypes.h"
13#include "base/gtest_prod_util.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/string16.h"
16#include "base/synchronization/waitable_event.h"
17#include "chrome/browser/common/cancelable_request.h"
18#include "chrome/browser/favicon/favicon_service.h"
19#include "chrome/browser/history/android/android_history_provider_service.h"
20#include "chrome/browser/history/history_types.h"
21
22// This class is JNI implementation of
23// org.chromium.chrome.database.SqliteCursor, it uses the AndroidStatement to
24// iterate among the result rows. This is not thread safe, all methods should
25// be called from the same non-UI thread which typical is the Java thread.
26//
27// This class can not be in history namespace because the class name has to
28// match to the generated sqlite_cursor_jni.h.
29class SQLiteCursor {
30 public:
31  // Mapping to the column type definitions in java.sql.Types.
32  enum JavaColumnType {
33    BLOB = 2004,
34    LONG_VAR_CHAR = -1,
35    NULL_TYPE = 0,
36    NUMERIC = 2,
37    DOUBLE = 8,
38  };
39
40  // This class is intended to be used only in unit tests.
41  //
42  // There are 2 threads in unit test, one is the UI thread, another is the DB
43  // thread, after the task posted into UI thread, the MessageLoop needs to run
44  // to execute the task. The OnPostMoveToTask() and the OnPostGetFaviconTask()
45  // give unit tests a chance to run the message loop before event_.Wait is
46  // invoked, The OnGetMoveToResult() and OnGetFaviconResult() is used to notify
47  // the test observer in the UI thread when the task's result comes back, it
48  // calls MessageLoop::Quit() to exit the loop, then the event.Wait() is
49  // called. Basically, Two threads are used to simulate 3 threads' behavior
50  // here.
51  // The whole observer design is only for test purpose and should only be used
52  // in unit test.
53  class TestObserver {
54   public:
55    TestObserver();
56
57    // Notify the MoveTo task has been posted to UI thread.
58    virtual void OnPostMoveToTask() = 0;
59    // Notify the MoveTo result has been gotten in UI thread.
60    virtual void OnGetMoveToResult() = 0;
61    // Notify the GetFavicon task has been posted to UI thread.
62    virtual void OnPostGetFaviconTask() = 0;
63    // Notify the GetFavicon result has been gotten in UI thread.
64    virtual void OnGetFaviconResult() = 0;
65
66   protected:
67    virtual ~TestObserver();
68  };
69
70  // Returns org.chromium.chrome.SQLiteCursor java object by creating
71  // SQLitCursor native and java objects, then bind them together.
72  static base::android::ScopedJavaLocalRef<jobject> NewJavaSqliteCursor(
73      JNIEnv* env,
74      const std::vector<std::string>& column_names,
75      history::AndroidStatement* statement,
76      AndroidHistoryProviderService* service,
77      FaviconService* favicon_service);
78
79  static bool RegisterSqliteCursor(JNIEnv* env);
80
81  // JNI methods -----------------------------------------------------------
82
83  // Returns the result row count.
84  jint GetCount(JNIEnv* env, jobject obj);
85
86  // Returns the result's columns' name.
87  base::android::ScopedJavaLocalRef<jobjectArray> GetColumnNames(
88      JNIEnv* env,
89      jobject obj);
90
91  // Returns the given column value as jstring.
92  base::android::ScopedJavaLocalRef<jstring> GetString(JNIEnv* env,
93                                                       jobject obj,
94                                                       jint column);
95
96  // Returns the given column value as jlong.
97  jlong GetLong(JNIEnv* env, jobject obj, jint column);
98
99  // Returns the given column value as int.
100  jint GetInt(JNIEnv* env, jobject obj, jint column);
101
102  // Returns the given column value as double.
103  jdouble GetDouble(JNIEnv* env, jobject obj, jint column);
104
105  // Returns the given column value as jbyteArray.
106  base::android::ScopedJavaLocalRef<jbyteArray> GetBlob(JNIEnv* env,
107                                                        jobject obj,
108                                                        jint column);
109
110  // Return JNI_TRUE if the give column value is NULL, JNI_FALSE otherwise.
111  jboolean IsNull(JNIEnv* env, jobject obj, jint column);
112
113  // Moves the cursor to |pos|, returns new position.
114  // If the returned position is not equal to |pos|, then the cursor points to
115  // the last row.
116  jint MoveTo(JNIEnv* env, jobject obj, jint pos);
117
118  // Returns the type of column.
119  jint GetColumnType(JNIEnv* env, jobject obj, jint column);
120
121  // Called from Java to relase this object.
122  void Destroy(JNIEnv* env, jobject obj);
123
124 private:
125  FRIEND_TEST_ALL_PREFIXES(SQLiteCursorTest, Run);
126
127  // |column_names| is the column names of this cursor, the sequence of name
128  // should match the sql query's projection name.
129  // |statement| is query's statement which bound the variables. This class
130  // take the ownership of |statement|.
131  SQLiteCursor(const std::vector<std::string>& column_names,
132               history::AndroidStatement* statement,
133               AndroidHistoryProviderService* service,
134               FaviconService* favicon_service);
135
136  virtual ~SQLiteCursor();
137
138  // This method is for testing only.
139  void set_test_observer(TestObserver* test_observer) {
140    test_observer_ = test_observer;
141  }
142
143  // Get Favicon from history backend.
144  bool GetFavicon(history::FaviconID id,
145                  std::vector<unsigned char>* image_data);
146
147  void GetFaviconForIDInUIThread(
148      history::FaviconID id,
149      CancelableRequestConsumerBase* consumer,
150      const FaviconService::FaviconRawCallback& callback);
151
152  // The Callback function of GetFavicon().
153  void OnFaviconData(FaviconService::Handle handle,
154                     const history::FaviconBitmapResult& bitmap_result);
155
156  // The callback function of MoveTo().
157  void OnMoved(AndroidHistoryProviderService::Handle handle,
158               int pos);
159
160  // Used to cancel all request on the UI thread during shutdown.
161  void CancelAllRequests(base::WaitableEvent* finished);
162
163  JavaColumnType GetColumnTypeInternal(int column);
164
165  // Runs the MoveStatement on UI thread.
166  void RunMoveStatementOnUIThread(int pos);
167
168  // The current row position, '-1' means the position before the first one.
169  int position_;
170
171  base::WaitableEvent event_;
172
173  // The wrapped history::AndroidStatement.
174  history::AndroidStatement* statement_;
175
176  // Result set columns' name
177  const std::vector<std::string> column_names_;
178
179  AndroidHistoryProviderService* service_;
180
181  FaviconService* favicon_service_;
182
183  CancelableRequestConsumer consumer_;
184
185  // The count of result rows.
186  int count_;
187
188  // The favicon image.
189  history::FaviconBitmapResult favicon_bitmap_result_;
190
191  TestObserver* test_observer_;
192
193  DISALLOW_COPY_AND_ASSIGN(SQLiteCursor);
194};
195
196#endif  // CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
197