// Copyright (c) 2012 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.

#ifndef CONTENT_PUBLIC_BROWSER_WEB_UI_MESSAGE_HANDLER_H_
#define CONTENT_PUBLIC_BROWSER_WEB_UI_MESSAGE_HANDLER_H_

#include <vector>

#include "base/gtest_prod_util.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/values.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_ui.h"

class WebUIBrowserTest;
class MojoWebUIBrowserTest;

namespace base {
class ListValue;
}

namespace content {

class TestWebUI;
class WebUI;
class WebUIImpl;

// Messages sent from the DOM are forwarded via the WebUI to handler
// classes. These objects are owned by WebUI and destroyed when the
// host is destroyed.
class CONTENT_EXPORT WebUIMessageHandler {
 public:
  WebUIMessageHandler() : javascript_allowed_(false), web_ui_(nullptr) {}
  virtual ~WebUIMessageHandler() {}

  // Call this when a page should not receive JavaScript messages.
  void DisallowJavascript();

  // Called from tests to toggle JavaScript to catch bugs. If AllowJavascript()
  // is needed from production code, just publicize AllowJavascript() instead.
  void AllowJavascriptForTesting();

  bool IsJavascriptAllowed() const;

 protected:
  FRIEND_TEST_ALL_PREFIXES(WebUIMessageHandlerTest, ExtractIntegerValue);
  FRIEND_TEST_ALL_PREFIXES(WebUIMessageHandlerTest, ExtractDoubleValue);
  FRIEND_TEST_ALL_PREFIXES(WebUIMessageHandlerTest, ExtractStringValue);

  // This method must be called once the handler's corresponding JavaScript
  // component is initialized. In practice, it should be called from a WebUI
  // message handler similar to: 'initializeFooPage' or 'getInitialState'.
  //
  // There should be ideally one or two calls to this per handler, as JavaScript
  // components should have a specific message that signals that it's initalized
  // and ready to receive events from the C++ handler.
  //
  // This should never be called from a function that is not a message handler.
  // This should never be called from a C++ callback used as a reply for a
  // posted task or asynchronous operation.
  void AllowJavascript();

  // Helper methods:

  // Extract an integer value from a list Value.
  static bool ExtractIntegerValue(const base::ListValue* value, int* out_int);

  // Extract a floating point (double) value from a list Value.
  static bool ExtractDoubleValue(const base::ListValue* value,
                                 double* out_value);

  // Extract a string value from a list Value.
  static base::string16 ExtractStringValue(const base::ListValue* value);

  // This is where subclasses specify which messages they'd like to handle and
  // perform any additional initialization.. At this point web_ui() will return
  // the associated WebUI object.
  virtual void RegisterMessages() = 0;

  // Will be called whenever JavaScript from this handler becomes allowed from
  // the disallowed state. Subclasses should override this method to register
  // observers that push JavaScript calls to the page.
  virtual void OnJavascriptAllowed() {}

  // Will be called whenever JavaScript from this handler becomes disallowed
  // from the allowed state. This will never be called before
  // OnJavascriptAllowed has been called. Subclasses should override this method
  // to deregister or disabled observers that push JavaScript calls to the page.
  virtual void OnJavascriptDisallowed() {}

  // Helper method for responding to Javascript requests initiated with
  // cr.sendWithPromise() (defined in cr.js) for the case where the returned
  // promise should be resolved (request succeeded).
  void ResolveJavascriptCallback(const base::Value& callback_id,
                                 const base::Value& response);

  // Helper method for responding to Javascript requests initiated with
  // cr.sendWithPromise() (defined in cr.js), for the case where the returned
  // promise should be rejected (request failed).
  void RejectJavascriptCallback(const base::Value& callback_id,
                                const base::Value& response);

  // Helper method for notifying Javascript listeners added with
  // cr.addWebUIListener() (defined in cr.js).
  template <typename... Values>
  void FireWebUIListener(const std::string& event_name,
                         const Values&... values) {
    // cr.webUIListenerCallback is a global JS function exposed from cr.js.
    CallJavascriptFunction("cr.webUIListenerCallback", base::Value(event_name),
                           values...);
  }

  // Call a Javascript function by sending its name and arguments down to
  // the renderer.  This is asynchronous; there's no way to get the result
  // of the call, and should be thought of more like sending a message to
  // the page.
  // All function names in WebUI must consist of only ASCII characters.
  // These functions will crash if JavaScript is not currently allowed.
  template <typename... Values>
  void CallJavascriptFunction(const std::string& function_name,
                              const Values&... values) {
    CHECK(IsJavascriptAllowed()) << "Cannot CallJavascriptFunction before "
                                    "explicitly allowing JavaScript.";

    // The CHECK above makes this call safe.
    web_ui()->CallJavascriptFunctionUnsafe(function_name, values...);
  }

  // Returns the attached WebUI for this handler.
  WebUI* web_ui() const { return web_ui_; }

  // Sets the attached WebUI - exposed to subclasses for testing purposes.
  void set_web_ui(WebUI* web_ui) { web_ui_ = web_ui; }

 private:
  // Provide external classes access to web_ui(), set_web_ui(), and
  // RenderViewReused.
  friend class TestWebUI;
  friend class WebUIImpl;
  friend class ::WebUIBrowserTest;
  friend class ::MojoWebUIBrowserTest;

  // TODO(dbeam): disallow JavaScript when a renderer process crashes.
  // http://crbug.com/610450

  // True if the page is for JavaScript calls from this handler.
  bool javascript_allowed_;

  WebUI* web_ui_;
};

}  // namespace content

#endif  // CONTENT_PUBLIC_BROWSER_WEB_UI_MESSAGE_HANDLER_H_
