js_asker.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright (c) 2015 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #ifndef ATOM_BROWSER_NET_JS_ASKER_H_
  5. #define ATOM_BROWSER_NET_JS_ASKER_H_
  6. #include "atom/common/native_mate_converters/net_converter.h"
  7. #include "base/callback.h"
  8. #include "base/memory/ref_counted.h"
  9. #include "base/memory/weak_ptr.h"
  10. #include "base/values.h"
  11. #include "content/public/browser/browser_thread.h"
  12. #include "net/base/net_errors.h"
  13. #include "net/http/http_response_headers.h"
  14. #include "net/url_request/url_request_context_getter.h"
  15. #include "net/url_request/url_request_job.h"
  16. #include "v8/include/v8.h"
  17. namespace atom {
  18. using JavaScriptHandler =
  19. base::Callback<void(const base::DictionaryValue&, v8::Local<v8::Value>)>;
  20. namespace internal {
  21. using BeforeStartCallback =
  22. base::Callback<void(v8::Isolate*, v8::Local<v8::Value>)>;
  23. using ResponseCallback =
  24. base::Callback<void(bool, std::unique_ptr<base::Value> options)>;
  25. // Ask handler for options in UI thread.
  26. void AskForOptions(v8::Isolate* isolate,
  27. const JavaScriptHandler& handler,
  28. std::unique_ptr<base::DictionaryValue> request_details,
  29. const BeforeStartCallback& before_start,
  30. const ResponseCallback& callback);
  31. // Test whether the |options| means an error.
  32. bool IsErrorOptions(base::Value* value, int* error);
  33. } // namespace internal
  34. template<typename RequestJob>
  35. class JsAsker : public RequestJob {
  36. public:
  37. JsAsker(net::URLRequest* request, net::NetworkDelegate* network_delegate)
  38. : RequestJob(request, network_delegate), weak_factory_(this) {}
  39. // Called by |CustomProtocolHandler| to store handler related information.
  40. void SetHandlerInfo(
  41. v8::Isolate* isolate,
  42. net::URLRequestContextGetter* request_context_getter,
  43. const JavaScriptHandler& handler) {
  44. isolate_ = isolate;
  45. request_context_getter_ = request_context_getter;
  46. handler_ = handler;
  47. }
  48. // Subclass should do initailze work here.
  49. virtual void BeforeStartInUI(v8::Isolate*, v8::Local<v8::Value>) {}
  50. virtual void StartAsync(std::unique_ptr<base::Value> options) = 0;
  51. net::URLRequestContextGetter* request_context_getter() const {
  52. return request_context_getter_;
  53. }
  54. private:
  55. // RequestJob:
  56. void Start() override {
  57. std::unique_ptr<base::DictionaryValue> request_details(
  58. new base::DictionaryValue);
  59. FillRequestDetails(request_details.get(), RequestJob::request());
  60. content::BrowserThread::PostTask(
  61. content::BrowserThread::UI, FROM_HERE,
  62. base::Bind(&internal::AskForOptions,
  63. isolate_,
  64. handler_,
  65. base::Passed(&request_details),
  66. base::Bind(&JsAsker::BeforeStartInUI,
  67. weak_factory_.GetWeakPtr()),
  68. base::Bind(&JsAsker::OnResponse,
  69. weak_factory_.GetWeakPtr())));
  70. }
  71. void GetResponseInfo(net::HttpResponseInfo* info) override {
  72. info->headers = new net::HttpResponseHeaders("");
  73. }
  74. // Called when the JS handler has sent the response, we need to decide whether
  75. // to start, or fail the job.
  76. void OnResponse(bool success, std::unique_ptr<base::Value> value) {
  77. int error = net::ERR_NOT_IMPLEMENTED;
  78. if (success && value && !internal::IsErrorOptions(value.get(), &error)) {
  79. StartAsync(std::move(value));
  80. } else {
  81. RequestJob::NotifyStartError(
  82. net::URLRequestStatus(net::URLRequestStatus::FAILED, error));
  83. }
  84. }
  85. v8::Isolate* isolate_;
  86. net::URLRequestContextGetter* request_context_getter_;
  87. JavaScriptHandler handler_;
  88. base::WeakPtrFactory<JsAsker> weak_factory_;
  89. DISALLOW_COPY_AND_ASSIGN(JsAsker);
  90. };
  91. } // namespace atom
  92. #endif // ATOM_BROWSER_NET_JS_ASKER_H_