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