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