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