• 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 "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 
23 class 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.
32 class 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.
set_test_observer(TestObserver * test_observer)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::FaviconRawBitmapCallback& callback);
157 
158   // The callback function of FaviconService::GetLargestRawFaviconForID().
159   void OnFaviconData(const favicon_base::FaviconRawBitmapResult& 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::FaviconRawBitmapResult 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