Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2011 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 "base/utf_string_conversions.h"
      6 #include "chrome/browser/browser_process.h"
      7 #include "chrome/browser/utility_process_host.h"
      8 #include "chrome/test/in_process_browser_test.h"
      9 #include "chrome/test/ui_test_utils.h"
     10 #include "content/browser/renderer_host/resource_dispatcher_host.h"
     11 #include "content/common/indexed_db_key.h"
     12 #include "content/common/serialized_script_value.h"
     13 #include "googleurl/src/gurl.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
     16 #include "webkit/glue/idb_bindings.h"
     17 #include "webkit/glue/web_io_operators.h"
     18 
     19 using WebKit::WebSerializedScriptValue;
     20 
     21 // Sanity test, check the function call directly outside the sandbox.
     22 TEST(IDBKeyPathWithoutSandbox, Value) {
     23   char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
     24   std::vector<WebSerializedScriptValue> serialized_values;
     25   serialized_values.push_back(
     26       WebSerializedScriptValue::fromString(string16(data, arraysize(data))));
     27   serialized_values.push_back(
     28       WebSerializedScriptValue::fromString(string16()));
     29 
     30   std::vector<WebKit::WebIDBKey> values;
     31   string16 key_path(UTF8ToUTF16("foo"));
     32   bool error = webkit_glue::IDBKeysFromValuesAndKeyPath(
     33       serialized_values, key_path, &values);
     34 
     35   ASSERT_EQ(size_t(2), values.size());
     36   ASSERT_EQ(WebKit::WebIDBKey::StringType, values[0].type());
     37   ASSERT_EQ(UTF8ToUTF16("zoo"), values[0].string());
     38   ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[1].type());
     39   ASSERT_FALSE(error);
     40 
     41   values.clear();
     42   key_path = UTF8ToUTF16("PropertyNotAvailable");
     43   error = webkit_glue::IDBKeysFromValuesAndKeyPath(
     44       serialized_values, key_path, &values);
     45 
     46   ASSERT_EQ(size_t(2), values.size());
     47   ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[0].type());
     48   ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[1].type());
     49   ASSERT_FALSE(error);
     50 
     51   values.clear();
     52   key_path = UTF8ToUTF16("!+Invalid[KeyPath[[[");
     53   error = webkit_glue::IDBKeysFromValuesAndKeyPath(
     54       serialized_values, key_path, &values);
     55 
     56   ASSERT_TRUE(error);
     57   ASSERT_EQ(size_t(2), values.size());
     58   ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[0].type());
     59   ASSERT_EQ(WebKit::WebIDBKey::InvalidType, values[1].type());
     60 }
     61 
     62 class IDBKeyPathHelper : public UtilityProcessHost::Client {
     63  public:
     64   IDBKeyPathHelper()
     65       : expected_id_(0),
     66         utility_process_host_(NULL),
     67         value_for_key_path_failed_(false) {
     68   }
     69 
     70   void CreateUtilityProcess() {
     71     if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     72       BrowserThread::PostTask(
     73           BrowserThread::IO, FROM_HERE,
     74           NewRunnableMethod(this, &IDBKeyPathHelper::CreateUtilityProcess));
     75       return;
     76     }
     77     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     78     utility_process_host_ =
     79         new UtilityProcessHost(this, BrowserThread::IO);
     80     utility_process_host_->StartBatchMode();
     81     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
     82                             new MessageLoop::QuitTask());
     83   }
     84 
     85   void DestroyUtilityProcess() {
     86     if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
     87       BrowserThread::PostTask(
     88           BrowserThread::IO, FROM_HERE,
     89           NewRunnableMethod(this, &IDBKeyPathHelper::DestroyUtilityProcess));
     90       return;
     91     }
     92     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     93     utility_process_host_->EndBatchMode();
     94     utility_process_host_ = NULL;
     95     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
     96                             new MessageLoop::QuitTask());
     97   }
     98 
     99   void SetExpectedKeys(int expected_id,
    100                        const std::vector<IndexedDBKey>& expected_keys,
    101                        bool failed) {
    102     expected_id_ = expected_id;
    103     expected_keys_ = expected_keys;
    104     value_for_key_path_failed_ = failed;
    105   }
    106 
    107   void SetExpectedValue(const SerializedScriptValue& expected_value) {
    108     expected_value_ = expected_value;
    109   }
    110 
    111   void CheckValuesForKeyPath(
    112       int id, const std::vector<SerializedScriptValue>& serialized_values,
    113       const string16& key_path) {
    114     if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
    115       BrowserThread::PostTask(
    116           BrowserThread::IO, FROM_HERE,
    117           NewRunnableMethod(this, &IDBKeyPathHelper::CheckValuesForKeyPath,
    118                             id, serialized_values, key_path));
    119       return;
    120     }
    121     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    122     bool ret =
    123         utility_process_host_->StartIDBKeysFromValuesAndKeyPath(
    124             id, serialized_values, key_path);
    125     ASSERT_TRUE(ret);
    126   }
    127 
    128   void CheckInjectValue(const IndexedDBKey& key,
    129                         const SerializedScriptValue& value,
    130                         const string16& key_path) {
    131     if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
    132       BrowserThread::PostTask(
    133           BrowserThread::IO, FROM_HERE,
    134           NewRunnableMethod(this, &IDBKeyPathHelper::CheckInjectValue,
    135                             key, value, key_path));
    136       return;
    137     }
    138     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    139     bool ret = utility_process_host_->StartInjectIDBKey(key, value, key_path);
    140     ASSERT_TRUE(ret);
    141   }
    142 
    143   // UtilityProcessHost::Client
    144   virtual void OnIDBKeysFromValuesAndKeyPathSucceeded(
    145       int id, const std::vector<IndexedDBKey>& values) {
    146     EXPECT_EQ(expected_id_, id);
    147     EXPECT_FALSE(value_for_key_path_failed_);
    148     ASSERT_EQ(expected_keys_.size(), values.size());
    149     size_t pos = 0;
    150     for (std::vector<IndexedDBKey>::const_iterator i(values.begin());
    151          i != values.end(); ++i, ++pos) {
    152       ASSERT_EQ(expected_keys_[pos].type(), i->type());
    153       if (i->type() == WebKit::WebIDBKey::StringType) {
    154         ASSERT_EQ(expected_keys_[pos].string(), i->string());
    155       } else if (i->type() == WebKit::WebIDBKey::NumberType) {
    156         ASSERT_EQ(expected_keys_[pos].number(), i->number());
    157       }
    158     }
    159     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    160                             new MessageLoop::QuitTask());
    161   }
    162 
    163   virtual void OnIDBKeysFromValuesAndKeyPathFailed(int id) {
    164     EXPECT_TRUE(value_for_key_path_failed_);
    165     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    166                             new MessageLoop::QuitTask());
    167   }
    168 
    169   virtual void OnInjectIDBKeyFinished(
    170       const SerializedScriptValue& new_value) {
    171     EXPECT_EQ(expected_value_.data(), new_value.data());
    172     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    173                             new MessageLoop::QuitTask());
    174   }
    175 
    176 
    177  private:
    178   int expected_id_;
    179   std::vector<IndexedDBKey> expected_keys_;
    180   UtilityProcessHost* utility_process_host_;
    181   bool value_for_key_path_failed_;
    182   SerializedScriptValue expected_value_;
    183 };
    184 
    185 // This test fixture runs in the UI thread. However, most of the work done by
    186 // UtilityProcessHost (and wrapped by IDBKeyPathHelper above) happens on the IO
    187 // thread. This fixture delegates to IDBKeyPathHelper and blocks via
    188 // "ui_test_utils::RunMessageLoop()", until IDBKeyPathHelper posts a quit
    189 // message the MessageLoop.
    190 class ScopedIDBKeyPathHelper {
    191  public:
    192   ScopedIDBKeyPathHelper() {
    193     key_path_helper_ = new IDBKeyPathHelper();
    194     key_path_helper_->CreateUtilityProcess();
    195     ui_test_utils::RunMessageLoop();
    196   }
    197 
    198   ~ScopedIDBKeyPathHelper() {
    199     key_path_helper_->DestroyUtilityProcess();
    200     ui_test_utils::RunMessageLoop();
    201   }
    202 
    203   void SetExpectedKeys(int id, const std::vector<IndexedDBKey>& expected_keys,
    204                    bool failed) {
    205     key_path_helper_->SetExpectedKeys(id, expected_keys, failed);
    206   }
    207 
    208   void SetExpectedValue(const SerializedScriptValue& expected_value) {
    209     key_path_helper_->SetExpectedValue(expected_value);
    210   }
    211 
    212   void CheckValuesForKeyPath(
    213       int id,
    214       const std::vector<SerializedScriptValue>& serialized_script_values,
    215       const string16& key_path) {
    216     key_path_helper_->CheckValuesForKeyPath(id, serialized_script_values,
    217                                             key_path);
    218     ui_test_utils::RunMessageLoop();
    219   }
    220 
    221   void CheckInjectValue(const IndexedDBKey& key,
    222                         const SerializedScriptValue& value,
    223                         const string16& key_path) {
    224     key_path_helper_->CheckInjectValue(key, value, key_path);
    225     ui_test_utils::RunMessageLoop();
    226   }
    227 
    228  private:
    229   scoped_refptr<IDBKeyPathHelper> key_path_helper_;
    230 };
    231 
    232 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, IDBKeyPathExtract) {
    233   ScopedIDBKeyPathHelper scoped_helper;
    234   const int kId = 7;
    235   std::vector<IndexedDBKey> expected_keys;
    236   IndexedDBKey value;
    237   value.SetString(UTF8ToUTF16("zoo"));
    238   expected_keys.push_back(value);
    239 
    240   IndexedDBKey invalid_value;
    241   invalid_value.SetInvalid();
    242   expected_keys.push_back(invalid_value);
    243 
    244   scoped_helper.SetExpectedKeys(kId, expected_keys, false);
    245 
    246   char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
    247   std::vector<SerializedScriptValue> serialized_values;
    248   serialized_values.push_back(
    249       SerializedScriptValue(false, false, string16(data, arraysize(data))));
    250   serialized_values.push_back(
    251       SerializedScriptValue(true, false, string16()));
    252   scoped_helper.CheckValuesForKeyPath(
    253       kId, serialized_values, UTF8ToUTF16("foo"));
    254 }
    255 
    256 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, IDBKeyPathPropertyNotAvailable) {
    257   ScopedIDBKeyPathHelper scoped_helper;
    258   const int kId = 7;
    259   std::vector<IndexedDBKey> expected_keys;
    260   IndexedDBKey invalid_value;
    261   invalid_value.SetInvalid();
    262   expected_keys.push_back(invalid_value);
    263   expected_keys.push_back(invalid_value);
    264 
    265   scoped_helper.SetExpectedKeys(kId, expected_keys, false);
    266 
    267   char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
    268   std::vector<SerializedScriptValue> serialized_values;
    269   serialized_values.push_back(
    270       SerializedScriptValue(false, false, string16(data, arraysize(data))));
    271   serialized_values.push_back(
    272       SerializedScriptValue(true, false, string16()));
    273   scoped_helper.CheckValuesForKeyPath(kId, serialized_values,
    274                                       UTF8ToUTF16("PropertyNotAvailable"));
    275 }
    276 
    277 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, IDBKeyPathMultipleCalls) {
    278   ScopedIDBKeyPathHelper scoped_helper;
    279   const int kId = 7;
    280   std::vector<IndexedDBKey> expected_keys;
    281   IndexedDBKey invalid_value;
    282   invalid_value.SetInvalid();
    283   expected_keys.push_back(invalid_value);
    284   expected_keys.push_back(invalid_value);
    285 
    286   scoped_helper.SetExpectedKeys(kId, expected_keys, true);
    287 
    288   char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
    289   std::vector<SerializedScriptValue> serialized_values;
    290   serialized_values.push_back(
    291       SerializedScriptValue(false, false, string16(data, arraysize(data))));
    292   serialized_values.push_back(
    293       SerializedScriptValue(true, false, string16()));
    294   scoped_helper.CheckValuesForKeyPath(kId, serialized_values,
    295                                       UTF8ToUTF16("!+Invalid[KeyPath[[["));
    296 
    297   // Call again with the Utility process in batch mode and with valid keys.
    298   expected_keys.clear();
    299   IndexedDBKey value;
    300   value.SetString(UTF8ToUTF16("zoo"));
    301   expected_keys.push_back(value);
    302   expected_keys.push_back(invalid_value);
    303   scoped_helper.SetExpectedKeys(kId + 1, expected_keys, false);
    304   scoped_helper.CheckValuesForKeyPath(kId + 1, serialized_values,
    305                                       UTF8ToUTF16("foo"));
    306 }
    307 
    308 IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, InjectIDBKey) {
    309   // {foo: 'zoo'}
    310   const char16 data[] = {0x0353,0x6f66,0x536f,0x7a03,0x6f6f,0x017b};
    311   SerializedScriptValue value(false, false, string16(data, arraysize(data)));
    312   IndexedDBKey key;
    313   key.SetString(UTF8ToUTF16("myNewKey"));
    314 
    315   // {foo: 'zoo', bar: 'myNewKey'}
    316   const char16 expected_data[] = {0x353, 0x6f66, 0x536f, 0x7a03, 0x6f6f, 0x353,
    317                                   0x6162, 0x5372, 0x6d08, 0x4e79, 0x7765,
    318                                   0x654b, 0x7b79, 0x2};
    319   SerializedScriptValue expected_value(false, false,
    320                                        string16(expected_data,
    321                                                 arraysize(expected_data)));
    322 
    323   ScopedIDBKeyPathHelper scoped_helper;
    324   scoped_helper.SetExpectedValue(expected_value);
    325   scoped_helper.CheckInjectValue(key, value, UTF8ToUTF16("bar"));
    326 
    327   scoped_helper.SetExpectedValue(SerializedScriptValue());  // Expect null.
    328   scoped_helper.CheckInjectValue(key, value, UTF8ToUTF16("bad.key.path"));
    329 }
    330