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