Home | History | Annotate | Download | only in android
      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 #include "chrome/browser/history/android/sqlite_cursor.h"
      6 
      7 #include <jni.h>
      8 
      9 #include "base/android/jni_android.h"
     10 #include "base/android/jni_array.h"
     11 #include "base/android/jni_string.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "base/task/cancelable_task_tracker.h"
     14 #include "base/time/time.h"
     15 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
     16 #include "chrome/browser/favicon/chrome_favicon_client.h"
     17 #include "chrome/browser/favicon/chrome_favicon_client_factory.h"
     18 #include "chrome/browser/favicon/favicon_service.h"
     19 #include "chrome/browser/history/android/android_history_provider_service.h"
     20 #include "chrome/browser/history/android/android_time.h"
     21 #include "chrome/browser/history/history_service.h"
     22 #include "chrome/browser/history/history_service_factory.h"
     23 #include "chrome/common/chrome_constants.h"
     24 #include "chrome/test/base/testing_browser_process.h"
     25 #include "chrome/test/base/testing_profile.h"
     26 #include "chrome/test/base/testing_profile_manager.h"
     27 #include "components/bookmarks/test/bookmark_test_helpers.h"
     28 #include "components/history/core/android/android_history_types.h"
     29 #include "content/public/browser/browser_thread.h"
     30 #include "content/public/test/test_browser_thread.h"
     31 #include "content/public/test/test_utils.h"
     32 #include "testing/gtest/include/gtest/gtest.h"
     33 
     34 namespace {
     35 
     36 using base::Bind;
     37 using base::Time;
     38 using content::BrowserThread;
     39 using history::AndroidStatement;
     40 using history::HistoryAndBookmarkRow;
     41 using history::SearchRow;
     42 
     43 // The test cases in this file don't test the JNI interface which will be
     44 // covered in Java tests.
     45 class SQLiteCursorTest : public testing::Test,
     46                          public SQLiteCursor::TestObserver {
     47  public:
     48   SQLiteCursorTest()
     49       : profile_manager_(
     50           TestingBrowserProcess::GetGlobal()),
     51         ui_thread_(BrowserThread::UI, &message_loop_),
     52         file_thread_(BrowserThread::FILE, &message_loop_) {
     53   }
     54   virtual ~SQLiteCursorTest() {
     55   }
     56 
     57  protected:
     58   virtual void SetUp() OVERRIDE {
     59     // Setup the testing profile, so the bookmark_model_sql_handler could
     60     // get the bookmark model from it.
     61     ASSERT_TRUE(profile_manager_.SetUp());
     62     // It seems that the name has to be chrome::kInitialProfile, so it
     63     // could be found by ProfileManager::GetLastUsedProfile().
     64     testing_profile_ = profile_manager_.CreateTestingProfile(
     65         chrome::kInitialProfile);
     66 
     67     testing_profile_->CreateBookmarkModel(true);
     68     test::WaitForBookmarkModelToLoad(
     69         BookmarkModelFactory::GetForProfile(testing_profile_));
     70 
     71     testing_profile_->CreateFaviconService();
     72     ASSERT_TRUE(testing_profile_->CreateHistoryService(true, false));
     73     service_.reset(new AndroidHistoryProviderService(testing_profile_));
     74     hs_ = HistoryServiceFactory::GetForProfile(testing_profile_,
     75                                                Profile::EXPLICIT_ACCESS);
     76   }
     77 
     78   virtual void TearDown() OVERRIDE {
     79     testing_profile_->DestroyHistoryService();
     80     profile_manager_.DeleteTestingProfile(chrome::kInitialProfile);
     81     testing_profile_ = NULL;
     82   }
     83 
     84   // Override SQLiteCursor::TestObserver.
     85   virtual void OnPostMoveToTask() OVERRIDE {
     86     base::MessageLoop::current()->Run();
     87   }
     88 
     89   virtual void OnGetMoveToResult() OVERRIDE {
     90     base::MessageLoop::current()->Quit();
     91   }
     92 
     93   virtual void OnPostGetFaviconTask() OVERRIDE {
     94     base::MessageLoop::current()->Run();
     95   }
     96 
     97   virtual void OnGetFaviconResult() OVERRIDE {
     98     base::MessageLoop::current()->Quit();
     99   }
    100 
    101  protected:
    102   TestingProfileManager profile_manager_;
    103   base::MessageLoop message_loop_;
    104   content::TestBrowserThread ui_thread_;
    105   content::TestBrowserThread file_thread_;
    106   scoped_ptr<AndroidHistoryProviderService> service_;
    107   base::CancelableTaskTracker cancelable_tracker_;
    108   TestingProfile* testing_profile_;
    109   HistoryService* hs_;
    110 
    111 
    112  private:
    113   DISALLOW_COPY_AND_ASSIGN(SQLiteCursorTest);
    114 };
    115 
    116 class CallbackHelper : public base::RefCountedThreadSafe<CallbackHelper> {
    117  public:
    118   CallbackHelper()
    119       : success_(false),
    120         statement_(NULL) {
    121   }
    122 
    123   bool success() const {
    124     return success_;
    125   }
    126 
    127   AndroidStatement* statement() const {
    128     return statement_;
    129   }
    130 
    131   void OnInserted(int64 id) {
    132     success_ = id != 0;
    133     base::MessageLoop::current()->Quit();
    134   }
    135 
    136   void OnQueryResult(AndroidStatement* statement) {
    137     success_ = statement != NULL;
    138     statement_ = statement;
    139     base::MessageLoop::current()->Quit();
    140   }
    141 
    142  private:
    143   friend class base::RefCountedThreadSafe<CallbackHelper>;
    144   ~CallbackHelper() {
    145   }
    146 
    147   bool success_;
    148   AndroidStatement* statement_;
    149 
    150   DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
    151 };
    152 
    153 }  // namespace
    154 
    155 TEST_F(SQLiteCursorTest, Run) {
    156   HistoryAndBookmarkRow row;
    157   row.set_raw_url("http://www.google.com/");
    158   row.set_url(GURL("http://www.google.com/"));
    159   std::vector<unsigned char> favicon_data;
    160   favicon_data.push_back(1);
    161   base::RefCountedBytes *data_bytes =
    162       base::RefCountedBytes::TakeVector(&favicon_data);
    163   row.set_favicon(data_bytes);
    164   row.set_last_visit_time(Time::Now());
    165   row.set_visit_count(2);
    166   row.set_title(base::UTF8ToUTF16("cnn"));
    167   scoped_refptr<CallbackHelper> callback(new CallbackHelper());
    168 
    169   // Insert a row and verify it succeeded.
    170   service_->InsertHistoryAndBookmark(
    171       row,
    172       Bind(&CallbackHelper::OnInserted, callback.get()),
    173       &cancelable_tracker_);
    174 
    175   base::MessageLoop::current()->Run();
    176   EXPECT_TRUE(callback->success());
    177 
    178   std::vector<HistoryAndBookmarkRow::ColumnID> projections;
    179   projections.push_back(HistoryAndBookmarkRow::URL);
    180   projections.push_back(HistoryAndBookmarkRow::LAST_VISIT_TIME);
    181   projections.push_back(HistoryAndBookmarkRow::VISIT_COUNT);
    182   projections.push_back(HistoryAndBookmarkRow::FAVICON);
    183 
    184   // Query the inserted row.
    185   service_->QueryHistoryAndBookmarks(
    186       projections,
    187       std::string(),
    188       std::vector<base::string16>(),
    189       std::string(),
    190       Bind(&CallbackHelper::OnQueryResult, callback.get()),
    191       &cancelable_tracker_);
    192   base::MessageLoop::current()->Run();
    193   ASSERT_TRUE(callback->success());
    194 
    195   AndroidStatement* statement = callback->statement();
    196   std::vector<std::string> column_names;
    197   column_names.push_back(
    198       HistoryAndBookmarkRow::GetAndroidName(HistoryAndBookmarkRow::URL));
    199   column_names.push_back(HistoryAndBookmarkRow::GetAndroidName(
    200       HistoryAndBookmarkRow::LAST_VISIT_TIME));
    201   column_names.push_back(HistoryAndBookmarkRow::GetAndroidName(
    202       HistoryAndBookmarkRow::VISIT_COUNT));
    203   column_names.push_back(HistoryAndBookmarkRow::GetAndroidName(
    204       HistoryAndBookmarkRow::FAVICON));
    205 
    206   FaviconClient* favicon_client =
    207       ChromeFaviconClientFactory::GetForProfile(testing_profile_);
    208   FaviconService* favicon_service =
    209       new FaviconService(testing_profile_, favicon_client);
    210 
    211   SQLiteCursor* cursor = new SQLiteCursor(column_names, statement,
    212       service_.get(), favicon_service);
    213   cursor->set_test_observer(this);
    214   JNIEnv* env = base::android::AttachCurrentThread();
    215   EXPECT_EQ(1, cursor->GetCount(env, NULL));
    216   EXPECT_EQ(0, cursor->MoveTo(env, NULL, 0));
    217   EXPECT_EQ(row.url().spec(), base::android::ConvertJavaStringToUTF8(
    218       cursor->GetString(env, NULL, 0)).c_str());
    219   EXPECT_EQ(history::ToDatabaseTime(row.last_visit_time()),
    220       cursor->GetLong(env, NULL, 1));
    221   EXPECT_EQ(row.visit_count(), cursor->GetInt(env, NULL, 2));
    222   base::android::ScopedJavaLocalRef<jbyteArray> data =
    223       cursor->GetBlob(env, NULL, 3);
    224   std::vector<uint8> out;
    225   base::android::JavaByteArrayToByteVector(env, data.obj(), &out);
    226   EXPECT_EQ(data_bytes->data().size(), out.size());
    227   EXPECT_EQ(data_bytes->data()[0], out[0]);
    228   cursor->Destroy(env, NULL);
    229   // Cursor::Destroy posts the task in UI thread, run Message loop to release
    230   // the statement, delete SQLiteCursor itself etc.
    231   content::RunAllPendingInMessageLoop();
    232 }
    233