Fixed WebInspector inability to early report errors
authorKamil Klimek <k.klimek@partner.samsung.com>
Thu, 22 Jan 2015 19:22:09 +0000 (20:22 +0100)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
This is a little bit hacky implementation of port check, because in some
conditions it may happen that port will be taken between the check and
initialization of WebInspector on proper thread. Unfortunetly sockets
can't be passed between threads. They strictly belong to the thread they
were created.

Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=9549
Reviewed by: Janusz Majnert, Piotr Tworek

Change-Id: Iadac46a3152f96e944a274fb1a9afedc6260f386
Signed-off-by: Kamil Klimek <k.klimek@partner.samsung.com>
tizen_src/ewk/unittest/utc_blink_ewk_context_inspector_server_start_func.cpp
tizen_src/ewk/unittest/utc_blink_ewk_context_inspector_server_stop_func.cpp
tizen_src/ewk/unittest/utc_blink_ewk_view_inspector_server_stop_func.cpp
tizen_src/impl/devtools_delegate_efl.cc

index 7d48289..5a5e2bc 100644 (file)
@@ -29,6 +29,10 @@ TEST_F(utc_blink_ewk_context_inspector_server_start, Start)
 
   ASSERT_EQ(EINA_TRUE, ewk_view_url_set(GetEwkWebView(), "http://localhost:11111"));
   ASSERT_EQ(Success, EventLoopStart()) << "http://localhost:11111";
+
+  // need to stop server before next testcase, as context will be shared between tests
+  ASSERT_EQ(EINA_TRUE, ewk_context_inspector_server_stop(ewk_context_default_get()));
+  EventLoopWait(1);
 }
 
 /* @brief Try start inspector of context on unspecified TCP port*/
@@ -42,6 +46,9 @@ TEST_F(utc_blink_ewk_context_inspector_server_start, DefaultPort)
   ASSERT_EQ(EINA_TRUE, ewk_view_url_set(GetEwkWebView(), url));
   ASSERT_EQ(Success, EventLoopStart()) << url;
 
+  // need to stop server before next testcase, as context will be shared between tests
+  ASSERT_EQ(EINA_TRUE, ewk_context_inspector_server_stop(ewk_context_default_get()));
+  EventLoopWait(1);
 }
 
 /* @brief Negative test case of ewk_context_inspector_server_start on used port*/
@@ -50,4 +57,8 @@ TEST_F(utc_blink_ewk_context_inspector_server_start, UsedPort)
   ASSERT_EQ(11111, ewk_view_inspector_server_start(GetEwkWebView(),11111));
   EventLoopWait(1);
   ASSERT_NE(11111, ewk_context_inspector_server_start(ewk_context_default_get(),11111));
+
+  // need to stop server before next testcase, as context will be shared between tests
+  ASSERT_EQ(EINA_TRUE, ewk_view_inspector_server_stop(GetEwkWebView()));
+  EventLoopWait(1);
 }
index 15d7384..58925e1 100644 (file)
@@ -29,17 +29,21 @@ TEST_F(utc_blink_ewk_context_inspector_server_stop, WithOutStart)
 TEST_F(utc_blink_ewk_context_inspector_server_stop, StartStop)
 {
   ASSERT_EQ(11111, ewk_context_inspector_server_start(ewk_context_default_get(), 11111));
-  EventLoopWait(3);
+  EventLoopWait(1);
 
   ASSERT_EQ(EINA_TRUE, ewk_context_inspector_server_stop(ewk_context_default_get()));
-  EventLoopWait(3);
+  EventLoopWait(1);
 
   ASSERT_EQ(EINA_TRUE, ewk_view_url_set(GetEwkWebView(), "http://localhost:11111"));
   EXPECT_NE(Success, EventLoopStart());
 
   ASSERT_EQ(11111, ewk_context_inspector_server_start(ewk_context_default_get(), 11111));
-  EventLoopWait(3);
+  EventLoopWait(1);
 
   ASSERT_EQ(EINA_TRUE, ewk_view_url_set(GetEwkWebView(), "http://localhost:11111"));
   EXPECT_EQ(Success, EventLoopStart());
+
+  // must stop inspector because default context will be shared between tests
+  ASSERT_EQ(EINA_TRUE, ewk_context_inspector_server_stop(ewk_context_default_get()));
+  EventLoopWait(1);
 }
index b455fd0..3405977 100644 (file)
@@ -25,16 +25,17 @@ TEST_F(utc_blink_ewk_view_inspector_server_stop, StartStop)
   EventLoopWait(1);
 
   ASSERT_EQ(EINA_TRUE, ewk_view_url_set(GetEwkWebView(), "http://localhost:11111"));
-  ASSERT_EQ(Failure, EventLoopStart());
+  ASSERT_EQ(LoadFailure, EventLoopStart());
 
   /* Checking if server can be started, to make sure that was stopped successfully. */
   ASSERT_NE(0, ewk_view_inspector_server_start(GetEwkWebView(), 0));
   EventLoopWait(1);
   EXPECT_EQ(EINA_TRUE, ewk_view_inspector_server_stop(GetEwkWebView()));
+  EventLoopWait(1);
 }
 
 /* @brief Negative test case of ewk_view_inspector_server_stop */
 TEST_F(utc_blink_ewk_view_inspector_server_stop, StopWithoutStart)
 {
   EXPECT_NE(EINA_TRUE, ewk_view_inspector_server_stop(GetEwkWebView()));
-}
\ No newline at end of file
+}
index 969cebb..d387b49 100644 (file)
@@ -8,9 +8,11 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_http_handler.h"
 #include "content/public/browser/devtools_target.h"
 #include "content/shell/browser/shell.h"
 #include "grit/shell_resources.h"
 #include "grit/devtools_resources.h"
+#include "net/base/net_errors.h"
 #include "net/socket/tcp_server_socket.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "base/logging.h"
 #include <stdlib.h>
 #include <time.h>
 #include <unistd.h>
 
+using content::BrowserThread;
+
 namespace {
 
 // Copy of internal class implementation from
@@ -38,62 +42,76 @@ class TCPServerSocketFactory
       : content::DevToolsHttpHandler::ServerSocketFactory(
             address, port, backlog) {}
 
- private:
-  // content::DevToolsHttpHandler::ServerSocketFactory.
-  virtual scoped_ptr<net::ServerSocket> Create() const override {
+  virtual scoped_ptr<net::ServerSocket> Create() const {
     return scoped_ptr<net::ServerSocket>(
         new net::TCPServerSocket(NULL, net::NetLog::Source()));
   }
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(TCPServerSocketFactory);
 };
 
-scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>
-CreateSocketFactory(int& port) {
-  if (!port) {
-    const CommandLine* const command_line = CommandLine::ForCurrentProcess();
-    // See if the user specified a port on the command line (useful for
-    // automation). If not, use an ephemeral port by specifying 0.
-    if (command_line->HasSwitch(switches::kRemoteDebuggingPort)) {
-      int temp_port;
-      std::string port_str =
-          command_line->GetSwitchValueASCII(switches::kRemoteDebuggingPort);
-      if (base::StringToInt(port_str, &temp_port) &&
-          temp_port > 0 && temp_port < 65535) {
-        port = temp_port;
-      } else {
-        DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
-      }
-    } else {
-      //This random port is for old sdk widget debug.
-      srand( (unsigned)time(NULL) + (unsigned)getpid() );
-      port = random() % (65535 - 40000) + 40000;
-    }
-  }
-  return scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory>(
-      new TCPServerSocketFactory("0.0.0.0", port, 1));
-}
-
 }  // namespace
 
+
 namespace content {
 
 DevToolsDelegateEfl::DevToolsDelegateEfl(int port)
-    : port_(port)
+    : port_(0)
     , browser_context_(NULL)
     , devtools_http_handler_(NULL) {
-  std::string frontend_url;
+
+  // It's a hacky way to early detected if port is available. The problem is
+  // that the only thing we can do after checking is hope that noone will take
+  // the port until it's initialized on IO thread again. The best approach would
+  // be creating async callbacks that would inform when inspector server started
+  // and on which port.
+  static std::string addr = "0.0.0.0";
+  scoped_ptr<net::ServerSocket> sock(new net::TCPServerSocket(NULL, net::NetLog::Source()));
+
+  const CommandLine* const command_line = CommandLine::ForCurrentProcess();
+  // See if the user specified a port on the command line (useful for
+  // automation). If not, use an ephemeral port by specifying 0.
+  if (!port && command_line->HasSwitch(switches::kRemoteDebuggingPort)) {
+    int temp_port = 0;
+    std::string port_str =
+    command_line->GetSwitchValueASCII(switches::kRemoteDebuggingPort);
+    base::StringToInt(port_str, &temp_port);
+    if (temp_port > 0 && temp_port < 65535) {
+      port = temp_port;
+    } else {
+      DLOG(WARNING) << "Invalid http debugger port number " << temp_port;
+    }
+  }
+
+  // why backlog is 1?
+  if (sock->ListenWithAddressAndPort(addr, port, 1) != net::OK) {
+    port_ = 0;
+    return;
+  }
+
+  net::IPEndPoint givenIp;
+  sock->GetLocalAddress(&givenIp);
+  port_ = givenIp.port();
+
+  scoped_ptr<content::DevToolsHttpHandler::ServerSocketFactory> factory(
+      new TCPServerSocketFactory(addr, port_, 1));
+
   devtools_http_handler_ =
-    content::DevToolsHttpHandler::Start(CreateSocketFactory(port_),
-       frontend_url, this, base::FilePath());
+    content::DevToolsHttpHandler::Start(factory.Pass(),
+       addr, this, base::FilePath());
 }
 
 DevToolsDelegateEfl::~DevToolsDelegateEfl() {
 }
 
 void DevToolsDelegateEfl::Stop() {
-  // The call below destroys this.
-  devtools_http_handler_->Stop();
+  if (devtools_http_handler_) {
+    // The call below destroys this.
+    devtools_http_handler_->Stop();
+  } else {
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
+  }
 }
 
 std::string DevToolsDelegateEfl::GetDiscoveryPageHTML() {