普通文本  |  276行  |  8.63 KB

// Copyright (c) 2011 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 "media/base/filters.h"
#include "media/base/mock_callback.h"
#include "media/base/mock_filter_host.h"
#include "media/base/mock_filters.h"
#include "net/base/net_errors.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
#include "webkit/glue/media/simple_data_source.h"
#include "webkit/mocks/mock_webframe.h"
#include "webkit/mocks/mock_weburlloader.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::StrictMock;
using ::testing::WithArgs;

using WebKit::WebURLError;
using WebKit::WebURLLoader;
using WebKit::WebURLRequest;
using WebKit::WebURLResponse;

namespace webkit_glue {

static const int kDataSize = 1024;
static const char kHttpUrl[] = "http://test";
static const char kHttpsUrl[] = "https://test";
static const char kFileUrl[] = "file://test";
static const char kDataUrl[] =
    "data:text/plain;base64,YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoK";
static const char kDataUrlDecoded[] = "abcdefghijklmnopqrstuvwxyz";
static const char kInvalidUrl[] = "whatever://test";
static const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing";
static const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2";
static const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2";
static const char kHttpRedirectToDifferentDomainUrl2[] = "http://test2/ing";

class SimpleDataSourceTest : public testing::Test {
 public:
  SimpleDataSourceTest() {
    for (int i = 0; i < kDataSize; ++i) {
      data_[i] = i;
    }
  }

  virtual ~SimpleDataSourceTest() {
  }

  void InitializeDataSource(const char* url,
                            media::MockStatusCallback* callback) {
    gurl_ = GURL(url);

    frame_.reset(new NiceMock<MockWebFrame>());
    url_loader_ = new NiceMock<MockWebURLLoader>();

    data_source_ = new SimpleDataSource(MessageLoop::current(),
                                        frame_.get());

    // There is no need to provide a message loop to data source.
    data_source_->set_host(&host_);
    data_source_->SetURLLoaderForTest(url_loader_);

    data_source_->Initialize(url, callback);
    MessageLoop::current()->RunAllPending();
  }

  void RequestSucceeded(bool is_loaded) {
    WebURLResponse response(gurl_);
    response.setExpectedContentLength(kDataSize);

    data_source_->didReceiveResponse(NULL, response);
    int64 size;
    EXPECT_TRUE(data_source_->GetSize(&size));
    EXPECT_EQ(kDataSize, size);

    for (int i = 0; i < kDataSize; ++i) {
      data_source_->didReceiveData(NULL, data_ + i, 1, 1);
    }

    EXPECT_CALL(host_, SetLoaded(is_loaded));

    InSequence s;
    EXPECT_CALL(host_, SetTotalBytes(kDataSize));
    EXPECT_CALL(host_, SetBufferedBytes(kDataSize));

    data_source_->didFinishLoading(NULL, 0);

    // Let the tasks to be executed.
    MessageLoop::current()->RunAllPending();
  }

  void RequestFailed() {
    InSequence s;

    WebURLError error;
    error.reason = net::ERR_FAILED;
    data_source_->didFail(NULL, error);

    // Let the tasks to be executed.
    MessageLoop::current()->RunAllPending();
  }

  void Redirect(const char* url) {
    GURL redirectUrl(url);
    WebKit::WebURLRequest newRequest(redirectUrl);
    WebKit::WebURLResponse redirectResponse(gurl_);

    data_source_->willSendRequest(url_loader_, newRequest, redirectResponse);

    MessageLoop::current()->RunAllPending();
  }

  void DestroyDataSource() {
    data_source_->Stop(media::NewExpectedCallback());
    MessageLoop::current()->RunAllPending();

    data_source_ = NULL;
  }

  void AsyncRead() {
    for (int i = 0; i < kDataSize; ++i) {
      uint8 buffer[1];

      EXPECT_CALL(*this, ReadCallback(1));
      data_source_->Read(
          i, 1, buffer,
          NewCallback(this, &SimpleDataSourceTest::ReadCallback));
      EXPECT_EQ(static_cast<uint8>(data_[i]), buffer[0]);
    }
  }

  MOCK_METHOD1(ReadCallback, void(size_t size));

 protected:
  GURL gurl_;
  scoped_ptr<MessageLoop> message_loop_;
  NiceMock<MockWebURLLoader>* url_loader_;
  scoped_refptr<SimpleDataSource> data_source_;
  StrictMock<media::MockFilterHost> host_;
  scoped_ptr<NiceMock<MockWebFrame> > frame_;

  char data_[kDataSize];

  DISALLOW_COPY_AND_ASSIGN(SimpleDataSourceTest);
};

TEST_F(SimpleDataSourceTest, InitializeHTTP) {
  InitializeDataSource(kHttpUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  RequestSucceeded(false);
  DestroyDataSource();
}

TEST_F(SimpleDataSourceTest, InitializeHTTPS) {
  InitializeDataSource(kHttpsUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  RequestSucceeded(false);
  DestroyDataSource();
}

TEST_F(SimpleDataSourceTest, InitializeFile) {
  InitializeDataSource(kFileUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  RequestSucceeded(true);
  DestroyDataSource();
}

TEST_F(SimpleDataSourceTest, InitializeData) {
  frame_.reset(new NiceMock<MockWebFrame>());
  url_loader_ = new NiceMock<MockWebURLLoader>();

  data_source_ = new SimpleDataSource(MessageLoop::current(),
                                      frame_.get());
  // There is no need to provide a message loop to data source.
  data_source_->set_host(&host_);
  data_source_->SetURLLoaderForTest(url_loader_);

  EXPECT_CALL(host_, SetLoaded(true));
  EXPECT_CALL(host_, SetTotalBytes(sizeof(kDataUrlDecoded)));
  EXPECT_CALL(host_, SetBufferedBytes(sizeof(kDataUrlDecoded)));

  data_source_->Initialize(kDataUrl,
      media::NewExpectedStatusCallback(media::PIPELINE_OK));
  MessageLoop::current()->RunAllPending();

  DestroyDataSource();
}

TEST_F(SimpleDataSourceTest, RequestFailed) {
  InitializeDataSource(kHttpUrl,
      media::NewExpectedStatusCallback(media::PIPELINE_ERROR_NETWORK));
  RequestFailed();
  DestroyDataSource();
}

TEST_F(SimpleDataSourceTest, StopWhenDownloading) {
  // The callback should be deleted, but not executed.
  // TODO(scherkus): should this really be the behaviour?  Seems strange...
  StrictMock<media::MockStatusCallback>* callback =
      new StrictMock<media::MockStatusCallback>();
  EXPECT_CALL(*callback, Destructor());

  InitializeDataSource(kHttpUrl, callback);

  EXPECT_CALL(*url_loader_, cancel());
  DestroyDataSource();
}

TEST_F(SimpleDataSourceTest, AsyncRead) {
  InitializeDataSource(kFileUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  RequestSucceeded(true);
  AsyncRead();
  DestroyDataSource();
}

// NOTE: This test will need to be reworked a little once
// http://code.google.com/p/chromium/issues/detail?id=72578
// is fixed.
TEST_F(SimpleDataSourceTest, HasSingleOrigin) {
  // Make sure no redirect case works as expected.
  InitializeDataSource(kHttpUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  RequestSucceeded(false);
  EXPECT_TRUE(data_source_->HasSingleOrigin());
  DestroyDataSource();

  // Test redirect to the same domain.
  InitializeDataSource(kHttpUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  Redirect(kHttpRedirectToSameDomainUrl1);
  RequestSucceeded(false);
  EXPECT_TRUE(data_source_->HasSingleOrigin());
  DestroyDataSource();

  // Test redirect twice to the same domain.
  InitializeDataSource(kHttpUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  Redirect(kHttpRedirectToSameDomainUrl1);
  Redirect(kHttpRedirectToSameDomainUrl2);
  RequestSucceeded(false);
  EXPECT_TRUE(data_source_->HasSingleOrigin());
  DestroyDataSource();

  // Test redirect to a different domain.
  InitializeDataSource(kHttpUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  Redirect(kHttpRedirectToDifferentDomainUrl1);
  RequestSucceeded(false);
  EXPECT_FALSE(data_source_->HasSingleOrigin());
  DestroyDataSource();

  // Test redirect to the same domain and then to a different domain.
  InitializeDataSource(kHttpUrl,
                       media::NewExpectedStatusCallback(media::PIPELINE_OK));
  Redirect(kHttpRedirectToSameDomainUrl1);
  Redirect(kHttpRedirectToDifferentDomainUrl1);
  RequestSucceeded(false);
  EXPECT_FALSE(data_source_->HasSingleOrigin());
  DestroyDataSource();
}

}  // namespace webkit_glue