blob: 390bae141fab828a1c0d092ba7debd720affc755 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/date_time_chooser_client.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
class ExternalDateTimeChooserTest : public testing::Test {
protected:
void SetUp() final {
dummy_page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600));
}
Document& GetDocument() { return dummy_page_holder_->GetDocument(); }
private:
std::unique_ptr<DummyPageHolder> dummy_page_holder_;
};
class TestDateTimeChooserClient final
: public GarbageCollected<TestDateTimeChooserClient>,
public DateTimeChooserClient {
public:
explicit TestDateTimeChooserClient(Element* element) : element_(element) {}
~TestDateTimeChooserClient() override {}
void Trace(Visitor* visitor) const override {
visitor->Trace(element_);
visitor->Trace(date_time_chooser_);
DateTimeChooserClient::Trace(visitor);
}
void SetDateTimeChooser(DateTimeChooser* date_time_chooser) {
date_time_chooser_ = date_time_chooser;
}
private:
// DateTimeChooserClient functions:
Element& OwnerElement() const override { return *element_; }
void DidChooseValue(const String&) override {}
void DidChooseValue(double value) override {
if (date_time_chooser_)
date_time_chooser_->EndChooser();
}
void DidEndChooser() override {}
Member<Element> element_;
Member<DateTimeChooser> date_time_chooser_;
};
// This is a regression test for crbug.com/974646. EndChooser can cause a crash
// when it's called twice because |client_| was already nullptr.
TEST_F(ExternalDateTimeChooserTest, EndChooserShouldNotCrash) {
ScopedInputMultipleFieldsUIForTest input_multiple_fields_ui(false);
auto* document = Document::CreateForTest();
auto* element = document->CreateRawElement(html_names::kInputTag);
auto* client = MakeGarbageCollected<TestDateTimeChooserClient>(element);
auto* external_date_time_chooser =
MakeGarbageCollected<ExternalDateTimeChooser>(client);
client->SetDateTimeChooser(external_date_time_chooser);
external_date_time_chooser->ResponseHandler(true, 0);
}
// This is a regression test for crbug.com/1022302. When the label and the value
// are the same in an option element,
// HTMLInputElement::SetupDateTimeChooserParameters had set a null value. This
// caused a crash because Mojo message pipe couldn't get a null pointer at the
// receiving side.
TEST_F(ExternalDateTimeChooserTest,
OpenDateTimeChooserShouldNotCrashWhenLabelAndValueIsTheSame) {
ScopedInputMultipleFieldsUIForTest input_multiple_fields_ui(false);
GetDocument().documentElement()->setInnerHTML(R"HTML(
<input id=test type="date" list="src" />
<datalist id="src">
<option value='2019-12-31'>Hint</option>
<option value='2019-12-30'/>
<option>2019-12-29</option> // This has the same value in label and
// value attribute.
</datalist>
)HTML");
GetDocument().View()->UpdateAllLifecyclePhasesForTest();
auto* input = To<HTMLInputElement>(GetDocument().getElementById("test"));
ASSERT_TRUE(input);
DateTimeChooserParameters params;
bool success = input->SetupDateTimeChooserParameters(params);
EXPECT_TRUE(success);
auto* client = MakeGarbageCollected<TestDateTimeChooserClient>(
GetDocument().documentElement());
auto* external_date_time_chooser =
MakeGarbageCollected<ExternalDateTimeChooser>(client);
client->SetDateTimeChooser(external_date_time_chooser);
external_date_time_chooser->OpenDateTimeChooser(GetDocument().GetFrame(),
params);
// Crash should not happen after calling OpenDateTimeChooser().
}
} // namespace blink