element is used by the EditorClientImpl class to insert
// characters received through the RenderWidget::OnHandleInputEvent()
// function.
view_->set_send_content_state_immediately(true);
LoadHTML(""
""
"
"
""
""
"
"
"
"
""
"");
ExecuteJavaScript("document.getElementById('test').focus();");
render_thread_.sink().ClearMessages();
// For each key code, we send three keyboard events.
// * Pressing only the key;
// * Pressing the key and a left-shift key, and;
// * Pressing the key and a right-alt (AltGr) key.
static const MockKeyboard::Modifiers kModifiers[] = {
MockKeyboard::NONE,
MockKeyboard::LEFT_SHIFT,
#if defined(OS_WIN)
MockKeyboard::RIGHT_ALT,
#endif
};
MockKeyboard::Layout layout = kLayouts[i].layout;
for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifiers); ++j) {
// Virtual key codes used for this test.
static const int kKeyCodes[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z',
app::VKEY_OEM_1,
app::VKEY_OEM_PLUS,
app::VKEY_OEM_COMMA,
app::VKEY_OEM_MINUS,
app::VKEY_OEM_PERIOD,
app::VKEY_OEM_2,
app::VKEY_OEM_3,
app::VKEY_OEM_4,
app::VKEY_OEM_5,
app::VKEY_OEM_6,
app::VKEY_OEM_7,
#if defined(OS_WIN)
// Unclear how to handle this on Linux.
app::VKEY_OEM_8,
#endif
};
MockKeyboard::Modifiers modifiers = kModifiers[j];
for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
// Send a keyboard event to the RenderView object.
// We should test a keyboard event only when the given keyboard-layout
// driver is installed in a PC and the driver can assign a Unicode
// charcter for the given tuple (layout, key-code, and modifiers).
int key_code = kKeyCodes[k];
std::wstring char_code;
if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
continue;
}
}
// Retrieve the text in the test page and compare it with the expected
// text created from a virtual-key code, a character code, and the
// modifier-key status.
const int kMaxOutputCharacters = 4096;
std::wstring output = UTF16ToWideHack(
GetMainFrame()->contentAsText(kMaxOutputCharacters));
EXPECT_EQ(kLayouts[i].expected_result, output);
}
#else
NOTIMPLEMENTED();
#endif
}
// Crashy, http://crbug.com/53247.
TEST_F(RenderViewTest, DISABLED_DidFailProvisionalLoadWithErrorForError) {
GetMainFrame()->enableViewSourceMode(true);
WebURLError error;
error.domain.fromUTF8("test_domain");
error.reason = net::ERR_FILE_NOT_FOUND;
error.unreachableURL = GURL("http://foo");
WebFrame* web_frame = GetMainFrame();
// An error occurred.
view_->didFailProvisionalLoad(web_frame, error);
// Frame should exit view-source mode.
EXPECT_FALSE(web_frame->isViewSourceModeEnabled());
}
TEST_F(RenderViewTest, DidFailProvisionalLoadWithErrorForCancellation) {
GetMainFrame()->enableViewSourceMode(true);
WebURLError error;
error.domain.fromUTF8("test_domain");
error.reason = net::ERR_ABORTED;
error.unreachableURL = GURL("http://foo");
WebFrame* web_frame = GetMainFrame();
// A cancellation occurred.
view_->didFailProvisionalLoad(web_frame, error);
// Frame should stay in view-source mode.
EXPECT_TRUE(web_frame->isViewSourceModeEnabled());
}
// Regression test for http://crbug.com/35011
TEST_F(RenderViewTest, JSBlockSentAfterPageLoad) {
// 1. Load page with JS.
std::string html = ""
""
""
""
""
""
"";
render_thread_.sink().ClearMessages();
LoadHTML(html.c_str());
// 2. Block JavaScript.
ContentSettings settings;
for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
settings.settings[i] = CONTENT_SETTING_ALLOW;
settings.settings[CONTENT_SETTINGS_TYPE_JAVASCRIPT] = CONTENT_SETTING_BLOCK;
view_->SetContentSettings(settings);
// Make sure no pending messages are in the queue.
ProcessPendingMessages();
render_thread_.sink().ClearMessages();
// 3. Reload page.
ViewMsg_Navigate_Params params;
std::string url_str = "data:text/html;charset=utf-8,";
url_str.append(html);
GURL url(url_str);
params.url = url;
params.navigation_type = ViewMsg_Navigate_Params::RELOAD;
view_->OnNavigate(params);
ProcessPendingMessages();
// 4. Verify that the notification that javascript was blocked is sent after
// the navigation notifiction is sent.
int navigation_index = -1;
int block_index = -1;
for (size_t i = 0; i < render_thread_.sink().message_count(); ++i) {
const IPC::Message* msg = render_thread_.sink().GetMessageAt(i);
if (msg->type() == ViewHostMsg_FrameNavigate::ID)
navigation_index = i;
if (msg->type() == ViewHostMsg_ContentBlocked::ID)
block_index = i;
}
EXPECT_NE(-1, navigation_index);
EXPECT_NE(-1, block_index);
EXPECT_LT(navigation_index, block_index);
}
// Regression test for http://crbug.com/41562
TEST_F(RenderViewTest, UpdateTargetURLWithInvalidURL) {
const GURL invalid_gurl("http://");
view_->setMouseOverURL(WebKit::WebURL(invalid_gurl));
EXPECT_EQ(invalid_gurl, view_->target_url_);
}
TEST_F(RenderViewTest, SendForms) {
// Don't want any delay for form state sync changes. This will still post a
// message so updates will get coalesced, but as soon as we spin the message
// loop, it will generate an update.
view_->set_send_content_state_immediately(true);
LoadHTML("
");
// Verify that "FormsSeen" sends the expected number of fields.
ProcessPendingMessages();
const IPC::Message* message = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_FormsSeen::ID);
ASSERT_NE(static_cast
(NULL), message);
ViewHostMsg_FormsSeen::Param params;
ViewHostMsg_FormsSeen::Read(message, ¶ms);
const std::vector& forms = params.a;
ASSERT_EQ(1UL, forms.size());
ASSERT_EQ(3UL, forms[0].fields.size());
EXPECT_TRUE(forms[0].fields[0].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("firstname"),
string16(),
ASCIIToUTF16("text"),
kDefaultMaxLength))) << forms[0].fields[0];
EXPECT_TRUE(forms[0].fields[1].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("middlename"),
string16(),
ASCIIToUTF16("text"),
kDefaultMaxLength))) << forms[0].fields[1];
EXPECT_TRUE(forms[0].fields[2].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("lastname"),
string16(),
ASCIIToUTF16("hidden"),
0))) << forms[0].fields[2];
// Verify that |didAcceptAutoFillSuggestion()| sends the expected number of
// fields.
WebFrame* web_frame = GetMainFrame();
WebDocument document = web_frame->document();
WebInputElement firstname =
document.getElementById("firstname").to();
// Accept suggestion that contains a label. Labeled items indicate AutoFill
// as opposed to Autocomplete. We're testing this distinction below with
// the |ViewHostMsg_FillAutoFillFormData::ID| message.
view_->didAcceptAutoFillSuggestion(firstname,
WebKit::WebString::fromUTF8("Johnny"),
WebKit::WebString::fromUTF8("Home"),
1,
-1);
ProcessPendingMessages();
const IPC::Message* message2 = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_FillAutoFillFormData::ID);
ASSERT_NE(static_cast(NULL), message2);
ViewHostMsg_FillAutoFillFormData::Param params2;
ViewHostMsg_FillAutoFillFormData::Read(message2, ¶ms2);
const FormData& form2 = params2.b;
ASSERT_EQ(3UL, form2.fields.size());
EXPECT_TRUE(form2.fields[0].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("firstname"),
string16(),
ASCIIToUTF16("text"),
kDefaultMaxLength))) << form2.fields[0];
EXPECT_TRUE(form2.fields[1].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("middlename"),
string16(),
ASCIIToUTF16("text"),
kDefaultMaxLength))) << form2.fields[1];
EXPECT_TRUE(form2.fields[2].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("lastname"),
string16(),
ASCIIToUTF16("hidden"),
0))) << form2.fields[2];
}
TEST_F(RenderViewTest, FillFormElement) {
// Don't want any delay for form state sync changes. This will still post a
// message so updates will get coalesced, but as soon as we spin the message
// loop, it will generate an update.
view_->set_send_content_state_immediately(true);
LoadHTML("");
// Verify that "FormsSeen" sends the expected number of fields.
ProcessPendingMessages();
const IPC::Message* message = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_FormsSeen::ID);
ASSERT_NE(static_cast(NULL), message);
ViewHostMsg_FormsSeen::Param params;
ViewHostMsg_FormsSeen::Read(message, ¶ms);
const std::vector& forms = params.a;
ASSERT_EQ(1UL, forms.size());
ASSERT_EQ(2UL, forms[0].fields.size());
EXPECT_TRUE(forms[0].fields[0].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("firstname"),
string16(),
ASCIIToUTF16("text"),
kDefaultMaxLength))) << forms[0].fields[0];
EXPECT_TRUE(forms[0].fields[1].StrictlyEqualsHack(
FormField(string16(),
ASCIIToUTF16("middlename"),
string16(),
ASCIIToUTF16("text"),
kDefaultMaxLength))) << forms[0].fields[1];
// Verify that |didAcceptAutoFillSuggestion()| sets the value of the expected
// field.
WebFrame* web_frame = GetMainFrame();
WebDocument document = web_frame->document();
WebInputElement firstname =
document.getElementById("firstname").to();
WebInputElement middlename =
document.getElementById("middlename").to();
middlename.setAutofilled(true);
// Accept a suggestion in a form that has been auto-filled. This triggers
// the direct filling of the firstname element with value parameter.
view_->didAcceptAutoFillSuggestion(firstname,
WebKit::WebString::fromUTF8("David"),
WebKit::WebString(),
0,
0);
ProcessPendingMessages();
const IPC::Message* message2 = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_FillAutoFillFormData::ID);
// No message should be sent in this case. |firstname| is filled directly.
ASSERT_EQ(static_cast(NULL), message2);
EXPECT_EQ(firstname.value(), WebKit::WebString::fromUTF8("David"));
}
// Tests that we send the right translatable for a page and that we respect the
// "no translate" meta-tag.
TEST_F(RenderViewTest, TranslatablePage) {
// Suppress the normal delay that occurs when the page is loaded before which
// the renderer sends the page contents to the browser.
view_->set_send_content_state_immediately(true);
LoadHTML("A random page with random content.");
ProcessPendingMessages();
const IPC::Message* message = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_PageContents::ID);
ASSERT_NE(static_cast(NULL), message);
ViewHostMsg_PageContents::Param params;
ViewHostMsg_PageContents::Read(message, ¶ms);
EXPECT_TRUE(params.e); // Translatable should be true.
render_thread_.sink().ClearMessages();
// Now the page specifies the META tag to prevent translation.
LoadHTML(""
"A random page with random content.");
ProcessPendingMessages();
message = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_PageContents::ID);
ASSERT_NE(static_cast(NULL), message);
ViewHostMsg_PageContents::Read(message, ¶ms);
EXPECT_FALSE(params.e); // Translatable should be false.
render_thread_.sink().ClearMessages();
// Try the alternate version of the META tag (content instead of value).
LoadHTML(""
"A random page with random content.");
ProcessPendingMessages();
message = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_PageContents::ID);
ASSERT_NE(static_cast(NULL), message);
ViewHostMsg_PageContents::Read(message, ¶ms);
EXPECT_FALSE(params.e); // Translatable should be false.
}
// Tests that the language meta tag takes precedence over the CLD when reporting
// the page's language.
TEST_F(RenderViewTest, LanguageMetaTag) {
// Suppress the normal delay that occurs when the page is loaded before which
// the renderer sends the page contents to the browser.
view_->set_send_content_state_immediately(true);
LoadHTML(""
"A random page with random content.");
ProcessPendingMessages();
const IPC::Message* message = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_PageContents::ID);
ASSERT_NE(static_cast(NULL), message);
ViewHostMsg_PageContents::Param params;
ViewHostMsg_PageContents::Read(message, ¶ms);
EXPECT_EQ("es", params.d);
render_thread_.sink().ClearMessages();
// Makes sure we support multiple languages specified.
LoadHTML(""
"A random page with random content.");
ProcessPendingMessages();
message = render_thread_.sink().GetUniqueMessageMatching(
ViewHostMsg_PageContents::ID);
ASSERT_NE(static_cast(NULL), message);
ViewHostMsg_PageContents::Read(message, ¶ms);
EXPECT_EQ("fr", params.d);
}