• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
TEST(IDBKeyPathWithoutSandbox,Value)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:
IDBKeyPathHelper()64   IDBKeyPathHelper()
65       : expected_id_(0),
66         utility_process_host_(NULL),
67         value_for_key_path_failed_(false) {
68   }
69 
CreateUtilityProcess()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 
DestroyUtilityProcess()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 
SetExpectedKeys(int expected_id,const std::vector<IndexedDBKey> & expected_keys,bool failed)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 
SetExpectedValue(const SerializedScriptValue & expected_value)107   void SetExpectedValue(const SerializedScriptValue& expected_value) {
108     expected_value_ = expected_value;
109   }
110 
CheckValuesForKeyPath(int id,const std::vector<SerializedScriptValue> & serialized_values,const string16 & key_path)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 
CheckInjectValue(const IndexedDBKey & key,const SerializedScriptValue & value,const string16 & key_path)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
OnIDBKeysFromValuesAndKeyPathSucceeded(int id,const std::vector<IndexedDBKey> & values)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 
OnIDBKeysFromValuesAndKeyPathFailed(int id)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 
OnInjectIDBKeyFinished(const SerializedScriptValue & new_value)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:
ScopedIDBKeyPathHelper()192   ScopedIDBKeyPathHelper() {
193     key_path_helper_ = new IDBKeyPathHelper();
194     key_path_helper_->CreateUtilityProcess();
195     ui_test_utils::RunMessageLoop();
196   }
197 
~ScopedIDBKeyPathHelper()198   ~ScopedIDBKeyPathHelper() {
199     key_path_helper_->DestroyUtilityProcess();
200     ui_test_utils::RunMessageLoop();
201   }
202 
SetExpectedKeys(int id,const std::vector<IndexedDBKey> & expected_keys,bool failed)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 
SetExpectedValue(const SerializedScriptValue & expected_value)208   void SetExpectedValue(const SerializedScriptValue& expected_value) {
209     key_path_helper_->SetExpectedValue(expected_value);
210   }
211 
CheckValuesForKeyPath(int id,const std::vector<SerializedScriptValue> & serialized_script_values,const string16 & key_path)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 
CheckInjectValue(const IndexedDBKey & key,const SerializedScriptValue & value,const string16 & key_path)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 
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,IDBKeyPathExtract)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 
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,IDBKeyPathPropertyNotAvailable)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 
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,IDBKeyPathMultipleCalls)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 
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest,InjectIDBKey)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