blob: fc934151f25c967be961708a189ecacb80bf9631 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
#define CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_
#include <memory>
#include <string>
#include <vector>
#include "base/android/scoped_java_ref.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/history/android/android_history_provider_service.h"
#include "components/favicon_base/favicon_callback.h"
#include "components/history/core/browser/history_types.h"
// This class is JNI implementation of
// org.chromium.chrome.database.SqliteCursor, it uses the AndroidStatement to
// iterate among the result rows. This is not thread safe, all methods should
// be called from the same non-UI thread which typical is the Java thread.
//
// This class can not be in history namespace because the class name has to
// match to the generated sqlite_cursor_jni.h.
class SQLiteCursor {
public:
// Mapping to the column type definitions in java.sql.Types.
enum JavaColumnType {
BLOB = 2004,
LONG_VAR_CHAR = -1,
NULL_TYPE = 0,
NUMERIC = 2,
DOUBLE = 8,
};
// This class is intended to be used only in unit tests.
//
// There are 2 threads in unit test, one is the UI thread, another is the DB
// thread, after the task posted into UI thread, the MessageLoop needs to run
// to execute the task. The OnPostMoveToTask() and the OnPostGetFaviconTask()
// give unit tests a chance to run the message loop before event_.Wait is
// invoked, The OnGetMoveToResult() and OnGetFaviconResult() is used to notify
// the test observer in the UI thread when the task's result comes back, it
// calls MessageLoop::QuitWhenIdle() to exit the loop, then the event.Wait()
// is called. Basically, Two threads are used to simulate 3 threads' behavior
// here.
// The whole observer design is only for test purpose and should only be used
// in unit test.
class TestObserver {
public:
TestObserver();
// Notify the MoveTo task has been posted to UI thread.
virtual void OnPostMoveToTask() = 0;
// Notify the MoveTo result has been gotten in UI thread.
virtual void OnGetMoveToResult() = 0;
// Notify the GetFavicon task has been posted to UI thread.
virtual void OnPostGetFaviconTask() = 0;
// Notify the GetFavicon result has been gotten in UI thread.
virtual void OnGetFaviconResult() = 0;
protected:
virtual ~TestObserver();
};
// Returns org.chromium.chrome.SQLiteCursor java object by creating
// SQLitCursor native and java objects, then bind them together.
static base::android::ScopedJavaLocalRef<jobject> NewJavaSqliteCursor(
JNIEnv* env,
const std::vector<std::string>& column_names,
history::AndroidStatement* statement,
AndroidHistoryProviderService* service);
// JNI methods -----------------------------------------------------------
// Returns the result row count.
jint GetCount(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
// Returns the result's columns' name.
base::android::ScopedJavaLocalRef<jobjectArray> GetColumnNames(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
// Returns the given column value as jstring.
base::android::ScopedJavaLocalRef<jstring> GetString(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint column);
// Returns the given column value as jlong.
jlong GetLong(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint column);
// Returns the given column value as int.
jint GetInt(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint column);
// Returns the given column value as double.
jdouble GetDouble(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint column);
// Returns the given column value as jbyteArray.
base::android::ScopedJavaLocalRef<jbyteArray> GetBlob(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint column);
// Return JNI_TRUE if the give column value is NULL, JNI_FALSE otherwise.
jboolean IsNull(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint column);
// Moves the cursor to |pos|, returns new position.
// If the returned position is not equal to |pos|, then the cursor points to
// the last row.
jint MoveTo(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint pos);
// Returns the type of column.
jint GetColumnType(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jint column);
// Called from Java to relase this object.
void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
private:
FRIEND_TEST_ALL_PREFIXES(SQLiteCursorTest, Run);
// |column_names| is the column names of this cursor, the sequence of name
// should match the sql query's projection name.
// |statement| is query's statement which bound the variables. This class
// take the ownership of |statement|.
SQLiteCursor(const std::vector<std::string>& column_names,
history::AndroidStatement* statement,
AndroidHistoryProviderService* service);
virtual ~SQLiteCursor();
// Destory SQLiteCursor object on UI thread. All cleanup need finish in UI
// thread.
void DestroyOnUIThread();
// This method is for testing only.
void set_test_observer(TestObserver* test_observer) {
test_observer_ = test_observer;
}
// Get Favicon from history backend.
bool GetFavicon(favicon_base::FaviconID id,
std::vector<unsigned char>* image_data);
void GetFaviconForIDInUIThread(
favicon_base::FaviconID id,
const favicon_base::FaviconRawBitmapCallback& callback);
// The callback function of FaviconService::GetLargestRawFaviconForID().
void OnFaviconData(const favicon_base::FaviconRawBitmapResult& bitmap_result);
// The callback function of MoveTo().
void OnMoved(int pos);
JavaColumnType GetColumnTypeInternal(int column);
// Runs the MoveStatement on UI thread.
void RunMoveStatementOnUIThread(int pos);
// The current row position, '-1' means the position before the first one.
int position_;
base::WaitableEvent event_;
// The wrapped history::AndroidStatement.
history::AndroidStatement* statement_;
// Result set columns' name
const std::vector<std::string> column_names_;
AndroidHistoryProviderService* service_;
// Live on UI thread.
std::unique_ptr<base::CancelableTaskTracker> tracker_;
// The count of result rows.
int count_;
// The favicon image.
favicon_base::FaviconRawBitmapResult favicon_bitmap_result_;
TestObserver* test_observer_;
DISALLOW_COPY_AND_ASSIGN(SQLiteCursor);
};
#endif // CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_