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. 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