OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tonic/dart_message_handler.h" | 5 #include "tonic/dart_message_handler.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "dart/runtime/include/dart_api.h" | 8 #include "dart/runtime/include/dart_api.h" |
9 #include "dart/runtime/include/dart_native_api.h" | 9 #include "dart/runtime/include/dart_native_api.h" |
10 #include "dart/runtime/include/dart_tools_api.h" | 10 #include "dart/runtime/include/dart_tools_api.h" |
11 #include "tonic/dart_error.h" | 11 #include "tonic/dart_error.h" |
12 #include "tonic/dart_state.h" | 12 #include "tonic/dart_state.h" |
13 | 13 |
14 namespace tonic { | 14 namespace tonic { |
15 | 15 |
16 DartMessageHandler::DartMessageHandler() | 16 DartMessageHandler::DartMessageHandler() |
17 : handled_first_message_(false), | 17 : handled_first_message_(false), |
| 18 quit_message_loop_when_isolate_exits_(true), |
| 19 isolate_exited_(false), |
| 20 isolate_had_uncaught_exception_error_(false), |
18 task_runner_(nullptr) { | 21 task_runner_(nullptr) { |
19 } | 22 } |
20 | 23 |
21 DartMessageHandler::~DartMessageHandler() { | 24 DartMessageHandler::~DartMessageHandler() { |
22 task_runner_ = nullptr; | 25 task_runner_ = nullptr; |
23 } | 26 } |
24 | 27 |
25 void DartMessageHandler::Initialize( | 28 void DartMessageHandler::Initialize( |
26 const scoped_refptr<base::SingleThreadTaskRunner>& runner) { | 29 const scoped_refptr<base::SingleThreadTaskRunner>& runner) { |
27 // Only can be called once. | 30 // Only can be called once. |
28 CHECK(!task_runner_); | 31 CHECK(!task_runner_); |
29 task_runner_ = runner; | 32 task_runner_ = runner; |
30 CHECK(task_runner_); | 33 CHECK(task_runner_); |
31 Dart_SetMessageNotifyCallback(MessageNotifyCallback); | 34 Dart_SetMessageNotifyCallback(MessageNotifyCallback); |
32 } | 35 } |
33 | 36 |
34 void DartMessageHandler::OnMessage(DartState* dart_state) { | 37 void DartMessageHandler::OnMessage(DartState* dart_state) { |
35 auto task_runner = dart_state->message_handler().task_runner(); | 38 auto task_runner = dart_state->message_handler().task_runner(); |
36 | 39 |
37 // Schedule a task to run on the message loop thread. | 40 // Schedule a task to run on the message loop thread. |
38 task_runner->PostTask(FROM_HERE, | 41 task_runner->PostTask(FROM_HERE, |
39 base::Bind(&HandleMessage, dart_state->GetWeakPtr())); | 42 base::Bind(&HandleMessage, dart_state->GetWeakPtr())); |
40 } | 43 } |
41 | 44 |
42 void DartMessageHandler::OnHandleMessage(DartState* dart_state) { | 45 void DartMessageHandler::OnHandleMessage(DartState* dart_state) { |
43 DartIsolateScope scope(dart_state->isolate()); | 46 DartIsolateScope scope(dart_state->isolate()); |
44 DartApiScope dart_api_scope; | 47 DartApiScope dart_api_scope; |
45 | 48 |
| 49 bool error = false; |
| 50 |
46 // On the first message, check if we should pause on isolate start. | 51 // On the first message, check if we should pause on isolate start. |
47 if (!handled_first_message()) { | 52 if (!handled_first_message()) { |
48 set_handled_first_message(true); | 53 set_handled_first_message(true); |
49 if (Dart_ShouldPauseOnStart()) { | 54 if (Dart_ShouldPauseOnStart()) { |
50 // Mark that we are paused on isolate start. | 55 // Mark that we are paused on isolate start. |
51 Dart_SetPausedOnStart(true); | 56 Dart_SetPausedOnStart(true); |
52 } | 57 } |
53 } | 58 } |
54 | 59 |
55 if (Dart_IsPausedOnStart()) { | 60 if (Dart_IsPausedOnStart()) { |
56 // We are paused on isolate start. Only handle service messages until we are | 61 // We are paused on isolate start. Only handle service messages until we are |
57 // requested to resume. | 62 // requested to resume. |
58 if (Dart_HasServiceMessages()) { | 63 if (Dart_HasServiceMessages()) { |
59 bool resume = Dart_HandleServiceMessages(); | 64 bool resume = Dart_HandleServiceMessages(); |
60 if (!resume) { | 65 if (!resume) { |
61 return; | 66 return; |
62 } | 67 } |
63 Dart_SetPausedOnStart(false); | 68 Dart_SetPausedOnStart(false); |
64 // We've resumed, handle *all* normal messages that are in the queue. | 69 // We've resumed, handle *all* normal messages that are in the queue. |
65 LogIfError(Dart_HandleMessages()); | 70 error = LogIfError(Dart_HandleMessages()); |
66 } | 71 } |
67 } else if (Dart_IsPausedOnExit()) { | 72 } else if (Dart_IsPausedOnExit()) { |
68 // We are paused on isolate exit. Only handle service messages until we are | 73 // We are paused on isolate exit. Only handle service messages until we are |
69 // requested to resume. | 74 // requested to resume. |
70 if (Dart_HasServiceMessages()) { | 75 if (Dart_HasServiceMessages()) { |
71 bool resume = Dart_HandleServiceMessages(); | 76 bool resume = Dart_HandleServiceMessages(); |
72 if (!resume) { | 77 if (!resume) { |
73 return; | 78 return; |
74 } | 79 } |
75 Dart_SetPausedOnExit(false); | 80 Dart_SetPausedOnExit(false); |
76 } | 81 } |
77 } else { | 82 } else { |
78 // We are processing messages normally. | 83 // We are processing messages normally. |
79 LogIfError(Dart_HandleMessage()); | 84 error = LogIfError(Dart_HandleMessage()); |
80 } | 85 } |
81 | 86 |
82 if (!Dart_HasLivePorts()) { | 87 if (error) { |
| 88 // Remember that we had an uncaught exception error. |
| 89 isolate_had_uncaught_exception_error_ = true; |
| 90 } |
| 91 |
| 92 if (error || !Dart_HasLivePorts()) { |
83 // The isolate has no live ports and would like to exit. | 93 // The isolate has no live ports and would like to exit. |
84 if (Dart_ShouldPauseOnExit()) { | 94 if (Dart_ShouldPauseOnExit()) { |
85 // Mark that we are paused on exit. | 95 // Mark that we are paused on exit. |
86 Dart_SetPausedOnExit(true); | 96 Dart_SetPausedOnExit(true); |
87 } else { | 97 } else { |
88 // Quit. | 98 isolate_exited_ = true; |
89 base::MessageLoop::current()->QuitWhenIdle(); | 99 if (quit_message_loop_when_isolate_exits()) { |
| 100 // Quit. |
| 101 base::MessageLoop::current()->QuitWhenIdle(); |
| 102 } |
90 } | 103 } |
91 } | 104 } |
92 } | 105 } |
93 | 106 |
94 void DartMessageHandler::MessageNotifyCallback(Dart_Isolate dest_isolate) { | 107 void DartMessageHandler::MessageNotifyCallback(Dart_Isolate dest_isolate) { |
95 auto dart_state = DartState::From(dest_isolate); | 108 auto dart_state = DartState::From(dest_isolate); |
96 CHECK(dart_state); | 109 CHECK(dart_state); |
97 dart_state->message_handler().OnMessage(dart_state); | 110 dart_state->message_handler().OnMessage(dart_state); |
98 } | 111 } |
99 | 112 |
100 void DartMessageHandler::HandleMessage( | 113 void DartMessageHandler::HandleMessage( |
101 base::WeakPtr<DartState> dart_state) { | 114 base::WeakPtr<DartState> dart_state) { |
102 if (!dart_state) | 115 if (!dart_state) |
103 return; | 116 return; |
104 dart_state->message_handler().OnHandleMessage(dart_state.get()); | 117 dart_state->message_handler().OnHandleMessage(dart_state.get()); |
105 } | 118 } |
106 | 119 |
107 } // namespace tonic | 120 } // namespace tonic |
OLD | NEW |