Home | History | Annotate | Download | only in webui
      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 "chrome/browser/ui/webui/sync_internals_ui.h"
      6 
      7 #include <cstddef>
      8 #include <string>
      9 
     10 #include "base/message_loop.h"
     11 #include "base/values.h"
     12 #include "chrome/browser/sync/js_arg_list.h"
     13 #include "chrome/browser/sync/js_test_util.h"
     14 #include "chrome/browser/sync/profile_sync_service_mock.h"
     15 #include "chrome/common/extensions/extension_messages.h"
     16 #include "chrome/test/profile_mock.h"
     17 #include "content/browser/browser_thread.h"
     18 #include "content/browser/renderer_host/test_render_view_host.h"
     19 #include "content/browser/tab_contents/test_tab_contents.h"
     20 #include "testing/gmock/include/gmock/gmock.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 namespace {
     24 
     25 using browser_sync::HasArgsAsList;
     26 using browser_sync::JsArgList;
     27 using testing::NiceMock;
     28 using testing::Return;
     29 using testing::StrictMock;
     30 
     31 // Subclass of SyncInternalsUI to mock out ExecuteJavascript.
     32 class TestSyncInternalsUI : public SyncInternalsUI {
     33  public:
     34   explicit TestSyncInternalsUI(TabContents* contents)
     35       : SyncInternalsUI(contents) {}
     36   virtual ~TestSyncInternalsUI() {}
     37 
     38   MOCK_METHOD1(ExecuteJavascript, void(const string16&));
     39 };
     40 
     41 class SyncInternalsUITest : public RenderViewHostTestHarness {
     42  protected:
     43   // We allocate memory for |sync_internals_ui_| but we don't
     44   // construct it.  This is because we want to set mock expectations
     45   // with its address before we construct it, and its constructor
     46   // calls into our mocks.
     47   SyncInternalsUITest()
     48       // The message loop is provided by RenderViewHostTestHarness.
     49       : ui_thread_(BrowserThread::UI, MessageLoopForUI::current()),
     50         test_sync_internals_ui_buf_(NULL),
     51         test_sync_internals_ui_constructor_called_(false) {}
     52 
     53   virtual void SetUp() {
     54     test_sync_internals_ui_buf_ = operator new(sizeof(TestSyncInternalsUI));
     55     test_sync_internals_ui_constructor_called_ = false;
     56     profile_.reset(new NiceMock<ProfileMock>());
     57     RenderViewHostTestHarness::SetUp();
     58   }
     59 
     60   virtual void TearDown() {
     61     if (test_sync_internals_ui_constructor_called_) {
     62       GetTestSyncInternalsUI()->~TestSyncInternalsUI();
     63     }
     64     operator delete(test_sync_internals_ui_buf_);
     65     RenderViewHostTestHarness::TearDown();
     66   }
     67 
     68   NiceMock<ProfileMock>* GetProfileMock() {
     69     return static_cast<NiceMock<ProfileMock>*>(profile());
     70   }
     71 
     72   // Set up boilerplate expectations for calls done during
     73   // SyncInternalUI's construction/destruction.
     74   void ExpectSetupTeardownCalls() {
     75     EXPECT_CALL(*GetProfileMock(), GetProfileSyncService())
     76         .WillRepeatedly(Return(&profile_sync_service_mock_));
     77 
     78     EXPECT_CALL(profile_sync_service_mock_, GetJsFrontend())
     79         .WillRepeatedly(Return(&mock_js_backend_));
     80 
     81     // Called by sync_ui_util::ConstructAboutInformation().
     82     EXPECT_CALL(profile_sync_service_mock_, HasSyncSetupCompleted())
     83         .WillRepeatedly(Return(false));
     84 
     85     // Called by SyncInternalsUI's constructor.
     86     EXPECT_CALL(mock_js_backend_,
     87                 AddHandler(GetTestSyncInternalsUIAddress()));
     88 
     89     // Called by SyncInternalUI's destructor.
     90     EXPECT_CALL(mock_js_backend_,
     91                 RemoveHandler(GetTestSyncInternalsUIAddress()));
     92   }
     93 
     94   // Like ExpectSetupTeardownCalls() but with a NULL
     95   // ProfileSyncService.
     96   void ExpectSetupTeardownCallsNullService() {
     97     EXPECT_CALL(*GetProfileMock(), GetProfileSyncService())
     98         .WillRepeatedly(Return(static_cast<ProfileSyncService*>(NULL)));
     99   }
    100 
    101   void ConstructTestSyncInternalsUI() {
    102     if (test_sync_internals_ui_constructor_called_) {
    103       ADD_FAILURE() << "ConstructTestSyncInternalsUI() should be called "
    104                     << "at most once per test";
    105       return;
    106     }
    107     new(test_sync_internals_ui_buf_) TestSyncInternalsUI(contents());
    108     test_sync_internals_ui_constructor_called_ = true;
    109   }
    110 
    111   TestSyncInternalsUI* GetTestSyncInternalsUI() {
    112     if (!test_sync_internals_ui_constructor_called_) {
    113       ADD_FAILURE() << "ConstructTestSyncInternalsUI() should be called "
    114                     << "before GetTestSyncInternalsUI()";
    115       return NULL;
    116     }
    117     return GetTestSyncInternalsUIAddress();
    118   }
    119 
    120   // Used for passing into EXPECT_CALL().
    121   TestSyncInternalsUI* GetTestSyncInternalsUIAddress() {
    122     EXPECT_TRUE(test_sync_internals_ui_buf_);
    123     return static_cast<TestSyncInternalsUI*>(test_sync_internals_ui_buf_);
    124   }
    125 
    126   StrictMock<ProfileSyncServiceMock> profile_sync_service_mock_;
    127   StrictMock<browser_sync::MockJsFrontend> mock_js_backend_;
    128 
    129  private:
    130   // Needed by |contents()|.
    131   BrowserThread ui_thread_;
    132   void* test_sync_internals_ui_buf_;
    133   bool test_sync_internals_ui_constructor_called_;
    134 };
    135 
    136 TEST_F(SyncInternalsUITest, HandleJsEvent) {
    137   ExpectSetupTeardownCalls();
    138 
    139   ConstructTestSyncInternalsUI();
    140 
    141   EXPECT_CALL(*GetTestSyncInternalsUI(),
    142               ExecuteJavascript(ASCIIToUTF16("testMessage(5,true);")));
    143 
    144   ListValue args;
    145   args.Append(Value::CreateIntegerValue(5));
    146   args.Append(Value::CreateBooleanValue(true));
    147   GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsArgList(args));
    148 }
    149 
    150 TEST_F(SyncInternalsUITest, HandleJsEventNullService) {
    151   ExpectSetupTeardownCallsNullService();
    152 
    153   ConstructTestSyncInternalsUI();
    154 
    155   EXPECT_CALL(*GetTestSyncInternalsUI(),
    156               ExecuteJavascript(ASCIIToUTF16("testMessage(5,true);")));
    157 
    158   ListValue args;
    159   args.Append(Value::CreateIntegerValue(5));
    160   args.Append(Value::CreateBooleanValue(true));
    161   GetTestSyncInternalsUI()->HandleJsEvent("testMessage", JsArgList(args));
    162 }
    163 
    164 TEST_F(SyncInternalsUITest, ProcessWebUIMessageBasic) {
    165   ExpectSetupTeardownCalls();
    166 
    167   ExtensionHostMsg_DomMessage_Params params;
    168   params.name = "testName";
    169   params.arguments.Append(Value::CreateIntegerValue(10));
    170 
    171   EXPECT_CALL(mock_js_backend_,
    172               ProcessMessage(params.name, HasArgsAsList(params.arguments),
    173                              GetTestSyncInternalsUIAddress()));
    174 
    175   ConstructTestSyncInternalsUI();
    176 
    177   GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
    178 }
    179 
    180 TEST_F(SyncInternalsUITest, ProcessWebUIMessageBasicNullService) {
    181   ExpectSetupTeardownCallsNullService();
    182 
    183   ConstructTestSyncInternalsUI();
    184 
    185   ExtensionHostMsg_DomMessage_Params params;
    186   params.name = "testName";
    187   params.arguments.Append(Value::CreateIntegerValue(5));
    188 
    189   // Should drop the message.
    190   GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
    191 }
    192 
    193 namespace {
    194 const char kAboutInfoCall[] =
    195     "onGetAboutInfoFinished({\"summary\":\"SYNC DISABLED\"});";
    196 }  // namespace
    197 
    198 TEST_F(SyncInternalsUITest, ProcessWebUIMessageGetAboutInfo) {
    199   ExpectSetupTeardownCalls();
    200 
    201   ExtensionHostMsg_DomMessage_Params params;
    202   params.name = "getAboutInfo";
    203 
    204   ConstructTestSyncInternalsUI();
    205 
    206   EXPECT_CALL(*GetTestSyncInternalsUI(),
    207               ExecuteJavascript(ASCIIToUTF16(kAboutInfoCall)));
    208 
    209   GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
    210 }
    211 
    212 TEST_F(SyncInternalsUITest, ProcessWebUIMessageGetAboutInfoNullService) {
    213   ExpectSetupTeardownCallsNullService();
    214 
    215   ExtensionHostMsg_DomMessage_Params params;
    216   params.name = "getAboutInfo";
    217 
    218   ConstructTestSyncInternalsUI();
    219 
    220   EXPECT_CALL(*GetTestSyncInternalsUI(),
    221               ExecuteJavascript(ASCIIToUTF16(kAboutInfoCall)));
    222 
    223   GetTestSyncInternalsUI()->ProcessWebUIMessage(params);
    224 }
    225 
    226 }  // namespace
    227