root/chrome/browser/history/android/sqlite_cursor.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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 <jni.h>
#include <vector>

#include "base/android/scoped_java_ref.h"
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/common/cancelable_request.h"
#include "chrome/browser/favicon/favicon_service.h"
#include "chrome/browser/history/android/android_history_provider_service.h"
#include "chrome/browser/history/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::Quit() 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,
      FaviconService* favicon_service);

  static bool RegisterSqliteCursor(JNIEnv* env);

  // JNI methods -----------------------------------------------------------

  // Returns the result row count.
  jint GetCount(JNIEnv* env, jobject obj);

  // Returns the result's columns' name.
  base::android::ScopedJavaLocalRef<jobjectArray> GetColumnNames(
      JNIEnv* env,
      jobject obj);

  // Returns the given column value as jstring.
  base::android::ScopedJavaLocalRef<jstring> GetString(JNIEnv* env,
                                                       jobject obj,
                                                       jint column);

  // Returns the given column value as jlong.
  jlong GetLong(JNIEnv* env, jobject obj, jint column);

  // Returns the given column value as int.
  jint GetInt(JNIEnv* env, jobject obj, jint column);

  // Returns the given column value as double.
  jdouble GetDouble(JNIEnv* env, jobject obj, jint column);

  // Returns the given column value as jbyteArray.
  base::android::ScopedJavaLocalRef<jbyteArray> GetBlob(JNIEnv* env,
                                                        jobject obj,
                                                        jint column);

  // Return JNI_TRUE if the give column value is NULL, JNI_FALSE otherwise.
  jboolean IsNull(JNIEnv* env, 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, jobject obj, jint pos);

  // Returns the type of column.
  jint GetColumnType(JNIEnv* env, jobject obj, jint column);

  // Called from Java to relase this object.
  void Destroy(JNIEnv* env, 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,
               FaviconService* favicon_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(chrome::FaviconID id,
                  std::vector<unsigned char>* image_data);

  void GetFaviconForIDInUIThread(
      chrome::FaviconID id,
      const FaviconService::FaviconRawCallback& callback);

  // The callback function of FaviconService::GetLargestRawFaviconForID().
  void OnFaviconData(const chrome::FaviconBitmapResult& bitmap_result);

  // The callback function of MoveTo().
  void OnMoved(AndroidHistoryProviderService::Handle handle, 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_;

  FaviconService* favicon_service_;

  // Live on UI thread.
  scoped_ptr<CancelableRequestConsumer> consumer_;
  scoped_ptr<base::CancelableTaskTracker> tracker_;

  // The count of result rows.
  int count_;

  // The favicon image.
  chrome::FaviconBitmapResult favicon_bitmap_result_;

  TestObserver* test_observer_;

  DISALLOW_COPY_AND_ASSIGN(SQLiteCursor);
};

#endif  // CHROME_BROWSER_HISTORY_ANDROID_SQLITE_CURSOR_H_

/* [<][>][^][v][top][bottom][index][help] */