text: // Copyright 2014 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 <algorithm>
  #include <vector>
  
  #include "base/command_line.h"
  #include "base/memory/scoped_ptr.h"
  #include "base/strings/utf_string_conversions.h"
  #include "components/autofill/content/browser/content_autofill_driver.h"
  #include "components/autofill/content/common/autofill_messages.h"
  #include "components/autofill/core/browser/autofill_external_delegate.h"
  #include "components/autofill/core/browser/autofill_manager.h"
  #include "components/autofill/core/browser/autofill_test_utils.h"
  #include "components/autofill/core/browser/test_autofill_client.h"
  #include "components/autofill/core/common/autofill_switches.h"
  #include "components/autofill/core/common/form_data_predictions.h"
  #include "content/public/browser/browser_context.h"
  #include "content/public/browser/navigation_details.h"
  #include "content/public/browser/web_contents.h"
  #include "content/public/common/frame_navigate_params.h"
  #include "content/public/test/mock_render_process_host.h"
  #include "content/public/test/test_renderer_host.h"
  #include "ipc/ipc_test_sink.h"
  #include "testing/gmock/include/gmock/gmock.h"
  #include "testing/gtest/include/gtest/gtest.h"
  
  namespace autofill {
  
  namespace {
  
  const std::string kAppLocale = "en-US";
  const AutofillManager::AutofillDownloadManagerState kDownloadState =
      AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER;
  
  }  // namespace
  
  class MockAutofillManager : public AutofillManager {
   public:
    MockAutofillManager(AutofillDriver* driver, AutofillClient* client)
        : AutofillManager(driver, client, kAppLocale, kDownloadState) {}
    virtual ~MockAutofillManager() {}
  
    MOCK_METHOD0(Reset, void());
  };
  
  class TestContentAutofillDriver : public ContentAutofillDriver {
   public:
    TestContentAutofillDriver(content::WebContents* contents,
                              AutofillClient* client)
        : ContentAutofillDriver(contents, client, kAppLocale, kDownloadState) {
      scoped_ptr<AutofillManager> autofill_manager(
          new MockAutofillManager(this, client));
      SetAutofillManager(autofill_manager.Pass());
    }
    virtual ~TestContentAutofillDriver() {}
  
    virtual MockAutofillManager* mock_autofill_manager() {
      return static_cast<MockAutofillManager*>(autofill_manager());
    }
  
    using ContentAutofillDriver::DidNavigateMainFrame;
  };
  
  class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
   public:
    virtual void SetUp() OVERRIDE {
      content::RenderViewHostTestHarness::SetUp();
  
      test_autofill_client_.reset(new TestAutofillClient());
      driver_.reset(new TestContentAutofillDriver(web_contents(),
                                                  test_autofill_client_.get()));
    }
  
    virtual void TearDown() OVERRIDE {
      // Reset the driver now to cause all pref observers to be removed and avoid
      // crashes that otherwise occur in the destructor.
      driver_.reset();
      content::RenderViewHostTestHarness::TearDown();
    }
  
   protected:
    // Searches for an |AutofillMsg_FillForm| message in the queue of sent IPC
    // messages. If none is present, returns false. Otherwise, extracts the first
    // |AutofillMsg_FillForm| message, fills the output parameters with the values
    // of the message's parameters, and clears the queue of sent messages.
    bool GetAutofillFillFormMessage(int* page_id, FormData* results) {
      const uint32 kMsgID = AutofillMsg_FillForm::ID;
      const IPC::Message* message =
          process()->sink().GetFirstMessageMatching(kMsgID);
      if (!message)
        return false;
      Tuple2<int, FormData> autofill_param;
      if (!AutofillMsg_FillForm::Read(message, &autofill_param))
        return false;
      if (page_id)
        *page_id = autofill_param.a;
      if (results)
        *results = autofill_param.b;
      process()->sink().ClearMessages();
      return true;
    }
  
    // Searches for an |AutofillMsg_PreviewForm| message in the queue of sent IPC
    // messages. If none is present, returns false. Otherwise, extracts the first
    // |AutofillMsg_PreviewForm| message, fills the output parameters with the
    // values of the message's parameters, and clears the queue of sent messages.
    bool GetAutofillPreviewFormMessage(int* page_id, FormData* results) {
      const uint32 kMsgID = AutofillMsg_PreviewForm::ID;
      const IPC::Message* message =
          process()->sink().GetFirstMessageMatching(kMsgID);
      if (!message)
        return false;
      Tuple2<int, FormData> autofill_param;
      if (!AutofillMsg_PreviewForm::Read(message, &autofill_param))
        return false;
      if (page_id)
        *page_id = autofill_param.a;
      if (results)
        *results = autofill_param.b;
      process()->sink().ClearMessages();
      return true;
    }
  
    // Searches for an |AutofillMsg_FieldTypePredictionsAvailable| message in the
    // queue of sent IPC messages. If none is present, returns false. Otherwise,
    // extracts the first |AutofillMsg_FieldTypePredictionsAvailable| message,
    // fills the output parameter with the values of the message's parameter, and
    // clears the queue of sent messages.
    bool GetFieldTypePredictionsAvailable(
        std::vector<FormDataPredictions>* predictions) {
      const uint32 kMsgID = AutofillMsg_FieldTypePredictionsAvailable::ID;
      const IPC::Message* message =
          process()->sink().GetFirstMessageMatching(kMsgID);
      if (!message)
        return false;
      Tuple1<std::vector<FormDataPredictions> > autofill_param;
      if (!AutofillMsg_FieldTypePredictionsAvailable::Read(message,
                                                           &autofill_param))
        return false;
      if (predictions)
        *predictions = autofill_param.a;
  
      process()->sink().ClearMessages();
      return true;
    }
  
    // Searches for a message matching |messageID| in the queue of sent IPC
    // messages. If none is present, returns false. Otherwise, extracts the first
    // matching message, fills the output parameter with the string16 from the
    // message's parameter, and clears the queue of sent messages.
    bool GetString16FromMessageWithID(uint32 messageID, base::string16* value) {
      const IPC::Message* message =
          process()->sink().GetFirstMessageMatching(messageID);
      if (!message)
        return false;
      Tuple1<base::string16> autofill_param;
      switch (messageID) {
        case AutofillMsg_FillFieldWithValue::ID:
          if (!AutofillMsg_FillFieldWithValue::Read(message, &autofill_param))
            return false;
          break;
        case AutofillMsg_PreviewFieldWithValue::ID:
          if (!AutofillMsg_PreviewFieldWithValue::Read(message, &autofill_param))
            return false;
          break;
        case AutofillMsg_AcceptDataListSuggestion::ID:
          if (!AutofillMsg_AcceptDataListSuggestion::Read(message,
                                                          &autofill_param))
            return false;
          break;
        default:
          NOTREACHED();
      }
      if (value)
        *value = autofill_param.a;
      process()->sink().ClearMessages();
      return true;
    }
  
    // Searches for a message matching |messageID| in the queue of sent IPC
    // messages. If none is present, returns false. Otherwise, clears the queue
    // of sent messages and returns true.
    bool HasMessageMatchingID(uint32 messageID) {
      const IPC::Message* message =
          process()->sink().GetFirstMessageMatching(messageID);
      if (!message)
        return false;
      process()->sink().ClearMessages();
      return true;
    }
  
    scoped_ptr<TestAutofillClient> test_autofill_client_;
    scoped_ptr<TestContentAutofillDriver> driver_;
  };
  
  TEST_F(ContentAutofillDriverTest, GetURLRequestContext) {
    net::URLRequestContextGetter* request_context =
        driver_->GetURLRequestContext();
    net::URLRequestContextGetter* expected_request_context =
        web_contents()->GetBrowserContext()->GetRequestContext();
    EXPECT_EQ(request_context, expected_request_context);
  }
  
  TEST_F(ContentAutofillDriverTest, NavigatedToDifferentPage) {
    EXPECT_CALL(*driver_->mock_autofill_manager(), Reset());
    content::LoadCommittedDetails details = content::LoadCommittedDetails();
    details.is_main_frame = true;
    details.is_in_page = false;
    ASSERT_TRUE(details.is_navigation_to_different_page());
    content::FrameNavigateParams params = content::FrameNavigateParams();
    driver_->DidNavigateMainFrame(details, params);
  }
  
  TEST_F(ContentAutofillDriverTest, NavigatedWithinSamePage) {
    EXPECT_CALL(*driver_->mock_autofill_manager(), Reset()).Times(0);
    content::LoadCommittedDetails details = content::LoadCommittedDetails();
    details.is_main_frame = false;
    ASSERT_TRUE(!details.is_navigation_to_different_page());
    content::FrameNavigateParams params = content::FrameNavigateParams();
    driver_->DidNavigateMainFrame(details, params);
  }
  
  TEST_F(ContentAutofillDriverTest, FormDataSentToRenderer_FillForm) {
    int input_page_id = 42;
    FormData input_form_data;
    test::CreateTestAddressFormData(&input_form_data);
    driver_->SendFormDataToRenderer(
        input_page_id, AutofillDriver::FORM_DATA_ACTION_FILL, input_form_data);
  
    int output_page_id = 0;
    FormData output_form_data;
    EXPECT_FALSE(
        GetAutofillPreviewFormMessage(&output_page_id, &output_form_data));
    EXPECT_TRUE(GetAutofillFillFormMessage(&output_page_id, &output_form_data));
    EXPECT_EQ(input_page_id, output_page_id);
    EXPECT_EQ(input_form_data, output_form_data);
  }
  
  TEST_F(ContentAutofillDriverTest, FormDataSentToRenderer_PreviewForm) {
    int input_page_id = 42;
    FormData input_form_data;
    test::CreateTestAddressFormData(&input_form_data);
    driver_->SendFormDataToRenderer(
        input_page_id, AutofillDriver::FORM_DATA_ACTION_PREVIEW, input_form_data);
  
    int output_page_id = 0;
    FormData output_form_data;
    EXPECT_FALSE(GetAutofillFillFormMessage(&output_page_id, &output_form_data));
    EXPECT_TRUE(
        GetAutofillPreviewFormMessage(&output_page_id, &output_form_data));
    EXPECT_EQ(input_page_id, output_page_id);
    EXPECT_EQ(input_form_data, output_form_data);
  }
  
  TEST_F(ContentAutofillDriverTest,
         TypePredictionsNotSentToRendererWhenDisabled) {
    FormData form;
    test::CreateTestAddressFormData(&form);
    FormStructure form_structure(form);
    std::vector<FormStructure*> forms(1, &form_structure);
    driver_->SendAutofillTypePredictionsToRenderer(forms);
    EXPECT_FALSE(GetFieldTypePredictionsAvailable(NULL));
  }
  
  TEST_F(ContentAutofillDriverTest, TypePredictionsSentToRendererWhenEnabled) {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kShowAutofillTypePredictions);
  
    FormData form;
    test::CreateTestAddressFormData(&form);
    FormStructure form_structure(form);
    std::vector<FormStructure*> forms(1, &form_structure);
    std::vector<FormDataPredictions> expected_type_predictions;
    FormStructure::GetFieldTypePredictions(forms, &expected_type_predictions);
    driver_->SendAutofillTypePredictionsToRenderer(forms);
  
    std::vector<FormDataPredictions> output_type_predictions;
    EXPECT_TRUE(GetFieldTypePredictionsAvailable(&output_type_predictions));
    EXPECT_EQ(expected_type_predictions, output_type_predictions);
  }
  
  TEST_F(ContentAutofillDriverTest, AcceptDataListSuggestion) {
    base::string16 input_value(base::ASCIIToUTF16("barfoo"));
    base::string16 output_value;
    driver_->RendererShouldAcceptDataListSuggestion(input_value);
    EXPECT_TRUE(GetString16FromMessageWithID(
        AutofillMsg_AcceptDataListSuggestion::ID, &output_value));
    EXPECT_EQ(input_value, output_value);
  }
  
  TEST_F(ContentAutofillDriverTest, ClearFilledFormSentToRenderer) {
    driver_->RendererShouldClearFilledForm();
    EXPECT_TRUE(HasMessageMatchingID(AutofillMsg_ClearForm::ID));
  }
  
  TEST_F(ContentAutofillDriverTest, ClearPreviewedFormSentToRenderer) {
    driver_->RendererShouldClearPreviewedForm();
    EXPECT_TRUE(HasMessageMatchingID(AutofillMsg_ClearPreviewedForm::ID));
  }
  
  TEST_F(ContentAutofillDriverTest, FillFieldWithValue) {
    base::string16 input_value(base::ASCIIToUTF16("barqux"));
    base::string16 output_value;
  
    driver_->RendererShouldFillFieldWithValue(input_value);
    EXPECT_TRUE(GetString16FromMessageWithID(AutofillMsg_FillFieldWithValue::ID,
                                             &output_value));
    EXPECT_EQ(input_value, output_value);
  }
  
  TEST_F(ContentAutofillDriverTest, PreviewFieldWithValue) {
    base::string16 input_value(base::ASCIIToUTF16("barqux"));
    base::string16 output_value;
    driver_->RendererShouldPreviewFieldWithValue(input_value);
    EXPECT_TRUE(GetString16FromMessageWithID(
        AutofillMsg_PreviewFieldWithValue::ID,
        &output_value));
    EXPECT_EQ(input_value, output_value);
  }
  
  }  // namespace autofill
  