Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: content/browser/service_worker/service_worker_version.cc

Issue 991743002: Service Worker: Coalesce the start worker timer into the timeout timer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review comments Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/browser/service_worker/service_worker_version.h" 5 #include "content/browser/service_worker/service_worker_version.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/memory/ref_counted.h" 8 #include "base/memory/ref_counted.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 47
48 // Time to wait until stopping an idle worker. 48 // Time to wait until stopping an idle worker.
49 const int kIdleWorkerTimeoutSeconds = 30; 49 const int kIdleWorkerTimeoutSeconds = 30;
50 50
51 // Default delay for scheduled update. 51 // Default delay for scheduled update.
52 const int kUpdateDelaySeconds = 1; 52 const int kUpdateDelaySeconds = 1;
53 53
54 // Timeout for waiting for a response to a ping. 54 // Timeout for waiting for a response to a ping.
55 const int kPingTimeoutSeconds = 30; 55 const int kPingTimeoutSeconds = 30;
56 56
57 // Timeout for the worker to start.
58 const int kStartWorkerTimeoutMinutes = 5;
59
60 // If the SW was destructed while starting up, how many seconds it 57 // If the SW was destructed while starting up, how many seconds it
61 // had to start up for this to be considered a timeout occurrence. 58 // had to start up for this to be considered a timeout occurrence.
62 const int kDestructedStartingWorkerTimeoutThresholdSeconds = 5; // 5 secs. 59 const int kDestructedStartingWorkerTimeoutThresholdSeconds = 5;
63 60
64 const char kClaimClientsStateErrorMesage[] = 61 const char kClaimClientsStateErrorMesage[] =
65 "Only the active worker can claim clients."; 62 "Only the active worker can claim clients.";
66 63
67 const char kClaimClientsShutdownErrorMesage[] = 64 const char kClaimClientsShutdownErrorMesage[] =
68 "Failed to claim clients due to Service Worker system shutdown."; 65 "Failed to claim clients due to Service Worker system shutdown.";
69 66
70 void RunSoon(const base::Closure& callback) { 67 void RunSoon(const base::Closure& callback) {
71 if (!callback.is_null()) 68 if (!callback.is_null())
72 base::MessageLoop::current()->PostTask(FROM_HERE, callback); 69 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 info.client_id = get<2>(it); 286 info.client_id = get<2>(it);
290 clients.push_back(info); 287 clients.push_back(info);
291 } 288 }
292 289
293 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 290 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
294 base::Bind(callback, clients)); 291 base::Bind(callback, clients));
295 } 292 }
296 293
297 } // namespace 294 } // namespace
298 295
296 const int ServiceWorkerVersion::kStartWorkerTimeoutMinutes = 5;
297
299 ServiceWorkerVersion::ServiceWorkerVersion( 298 ServiceWorkerVersion::ServiceWorkerVersion(
300 ServiceWorkerRegistration* registration, 299 ServiceWorkerRegistration* registration,
301 const GURL& script_url, 300 const GURL& script_url,
302 int64 version_id, 301 int64 version_id,
303 base::WeakPtr<ServiceWorkerContextCore> context) 302 base::WeakPtr<ServiceWorkerContextCore> context)
304 : version_id_(version_id), 303 : version_id_(version_id),
305 registration_id_(kInvalidServiceWorkerVersionId), 304 registration_id_(kInvalidServiceWorkerVersionId),
306 script_url_(script_url), 305 script_url_(script_url),
307 status_(NEW), 306 status_(NEW),
308 context_(context), 307 context_(context),
309 script_cache_map_(this, context), 308 script_cache_map_(this, context),
310 ping_timed_out_(false), 309 ping_state_(NOT_PINGING),
311 is_doomed_(false), 310 is_doomed_(false),
312 skip_waiting_(false), 311 skip_waiting_(false),
313 weak_factory_(this) { 312 weak_factory_(this) {
314 DCHECK(context_); 313 DCHECK(context_);
315 DCHECK(registration); 314 DCHECK(registration);
316 if (registration) { 315 if (registration) {
317 registration_id_ = registration->id(); 316 registration_id_ = registration->id();
318 scope_ = registration->pattern(); 317 scope_ = registration->pattern();
319 } 318 }
320 context_->AddLiveVersion(this); 319 context_->AddLiveVersion(this);
321 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); 320 embedded_worker_ = context_->embedded_worker_registry()->CreateWorker();
322 embedded_worker_->AddListener(this); 321 embedded_worker_->AddListener(this);
323 } 322 }
324 323
325 ServiceWorkerVersion::~ServiceWorkerVersion() { 324 ServiceWorkerVersion::~ServiceWorkerVersion() {
326 // The user may have closed the tab waiting for SW to start up. 325 // The user may have closed the tab waiting for SW to start up.
327 if (start_worker_timeout_timer_.IsRunning() && 326 if (GetTickDuration(start_time_) >
328 GetTickDuration(start_timing_) > 327 base::TimeDelta::FromSeconds(
329 base::TimeDelta::FromSeconds( 328 kDestructedStartingWorkerTimeoutThresholdSeconds)) {
330 kDestructedStartingWorkerTimeoutThresholdSeconds)) { 329 DCHECK(timeout_timer_.IsRunning());
330 DCHECK(!embedded_worker_->devtools_attached());
331 RecordStartWorkerResult(SERVICE_WORKER_ERROR_TIMEOUT); 331 RecordStartWorkerResult(SERVICE_WORKER_ERROR_TIMEOUT);
332 } 332 }
333 333
334 embedded_worker_->RemoveListener(this); 334 embedded_worker_->RemoveListener(this);
335 if (context_) 335 if (context_)
336 context_->RemoveLiveVersion(version_id_); 336 context_->RemoveLiveVersion(version_id_);
337 // EmbeddedWorker's dtor sends StopWorker if it's still running. 337 // EmbeddedWorker's dtor sends StopWorker if it's still running.
338 } 338 }
339 339
340 void ServiceWorkerVersion::SetStatus(Status status) { 340 void ServiceWorkerVersion::SetStatus(Status status) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); 385 RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED));
386 return; 386 return;
387 } 387 }
388 switch (running_status()) { 388 switch (running_status()) {
389 case RUNNING: 389 case RUNNING:
390 RunSoon(base::Bind(callback, SERVICE_WORKER_OK)); 390 RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
391 return; 391 return;
392 case STOPPING: 392 case STOPPING:
393 case STOPPED: 393 case STOPPED:
394 case STARTING: 394 case STARTING:
395 if (!start_worker_timeout_timer_.IsRunning()) 395 if (!timeout_timer_.IsRunning())
396 ScheduleStartWorkerTimeout(); 396 StartTimeoutTimer();
397 start_callbacks_.push_back(callback); 397 start_callbacks_.push_back(callback);
398 if (running_status() == STOPPED) { 398 if (running_status() == STOPPED) {
399 DCHECK(!cache_listener_.get()); 399 DCHECK(!cache_listener_.get());
400 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); 400 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_));
401 embedded_worker_->Start( 401 embedded_worker_->Start(
402 version_id_, scope_, script_url_, pause_after_download, 402 version_id_, scope_, script_url_, pause_after_download,
403 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, 403 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated,
404 weak_factory_.GetWeakPtr())); 404 weak_factory_.GetWeakPtr()));
405 } 405 }
406 return; 406 return;
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 return; 782 return;
783 is_doomed_ = true; 783 is_doomed_ = true;
784 if (!HasControllee()) 784 if (!HasControllee())
785 DoomInternal(); 785 DoomInternal();
786 } 786 }
787 787
788 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { 788 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) {
789 embedded_worker()->set_devtools_attached(attached); 789 embedded_worker()->set_devtools_attached(attached);
790 if (attached) { 790 if (attached) {
791 // Set to null time so we don't record the startup time metric. 791 // Set to null time so we don't record the startup time metric.
792 ClearTick(&start_timing_); 792 ClearTick(&start_time_);
793 return; 793 return;
794 } 794 }
795 // If devtools is detached try scheduling the timers for stopping the worker
796 // now.
797 if (!timeout_timer_.IsRunning()) 795 if (!timeout_timer_.IsRunning())
798 StartTimeoutTimer(); 796 StartTimeoutTimer();
799 if (!start_worker_timeout_timer_.IsRunning() && !start_callbacks_.empty())
800 ScheduleStartWorkerTimeout();
801 } 797 }
802 798
803 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( 799 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo(
804 const net::HttpResponseInfo& http_info) { 800 const net::HttpResponseInfo& http_info) {
805 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); 801 main_script_http_info_.reset(new net::HttpResponseInfo(http_info));
806 } 802 }
807 803
808 const net::HttpResponseInfo* 804 const net::HttpResponseInfo*
809 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { 805 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
810 return main_script_http_info_.get(); 806 return main_script_http_info_.get();
811 } 807 }
812 808
813 void ServiceWorkerVersion::OnScriptLoaded() { 809 void ServiceWorkerVersion::OnScriptLoaded() {
814 DCHECK_EQ(STARTING, running_status()); 810 DCHECK_EQ(STARTING, running_status());
815 StartTimeoutTimer(); 811 // Activate ping/pong now that JavaScript execution will start.
812 ping_state_ = PINGING;
816 } 813 }
817 814
818 void ServiceWorkerVersion::OnStarted() { 815 void ServiceWorkerVersion::OnStarted() {
819 DCHECK_EQ(RUNNING, running_status()); 816 DCHECK_EQ(RUNNING, running_status());
820 DCHECK(cache_listener_.get()); 817 DCHECK(cache_listener_.get());
821 RestartTick(&idle_time_); 818 RestartTick(&idle_time_);
822 819
823 // Fire all start callbacks. 820 // Fire all start callbacks.
824 scoped_refptr<ServiceWorkerVersion> protect(this); 821 scoped_refptr<ServiceWorkerVersion> protect(this);
825 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK); 822 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK);
826 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this)); 823 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this));
827 } 824 }
828 825
829 void ServiceWorkerVersion::OnStopped( 826 void ServiceWorkerVersion::OnStopped(
830 EmbeddedWorkerInstance::Status old_status) { 827 EmbeddedWorkerInstance::Status old_status) {
831 DCHECK_EQ(STOPPED, running_status()); 828 DCHECK_EQ(STOPPED, running_status());
832 scoped_refptr<ServiceWorkerVersion> protect(this); 829 scoped_refptr<ServiceWorkerVersion> protect(this);
833 830
834 bool should_restart = !is_doomed() && !start_callbacks_.empty() && 831 bool should_restart = !is_doomed() && !start_callbacks_.empty() &&
835 (old_status != EmbeddedWorkerInstance::STARTING); 832 (old_status != EmbeddedWorkerInstance::STARTING);
836 833
837 StopTimeoutTimer(); 834 StopTimeoutTimer();
838 if (ping_timed_out_) 835 if (ping_state_ == PING_TIMED_OUT)
839 should_restart = false; 836 should_restart = false;
840 837
841 // Fire all stop callbacks. 838 // Fire all stop callbacks.
842 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK); 839 RunCallbacks(this, &stop_callbacks_, SERVICE_WORKER_OK);
843 840
844 if (!should_restart) { 841 if (!should_restart) {
845 // Let all start callbacks fail. 842 // Let all start callbacks fail.
846 RunCallbacks(this, &start_callbacks_, 843 RunCallbacks(this, &start_callbacks_,
847 SERVICE_WORKER_ERROR_START_WORKER_FAILED); 844 SERVICE_WORKER_ERROR_START_WORKER_FAILED);
848 } 845 }
(...skipping 25 matching lines...) Expand all
874 871
875 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this)); 872 FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this));
876 873
877 // There should be no more communication from/to a stopped worker. Deleting 874 // There should be no more communication from/to a stopped worker. Deleting
878 // the listener prevents any pending completion callbacks from causing 875 // the listener prevents any pending completion callbacks from causing
879 // messages to be sent to the stopped worker. 876 // messages to be sent to the stopped worker.
880 cache_listener_.reset(); 877 cache_listener_.reset();
881 878
882 // Restart worker if we have any start callbacks and the worker isn't doomed. 879 // Restart worker if we have any start callbacks and the worker isn't doomed.
883 if (should_restart) { 880 if (should_restart) {
884 start_worker_timeout_timer_.Reset(); 881 if (embedded_worker_->devtools_attached())
882 ClearTick(&start_time_);
883 else
884 RestartTick(&start_time_);
885 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_)); 885 cache_listener_.reset(new ServiceWorkerCacheListener(this, context_));
886 embedded_worker_->Start( 886 embedded_worker_->Start(
887 version_id_, scope_, script_url_, false /* pause_after_download */, 887 version_id_, scope_, script_url_, false /* pause_after_download */,
888 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, 888 base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated,
889 weak_factory_.GetWeakPtr())); 889 weak_factory_.GetWeakPtr()));
890 } 890 }
891 } 891 }
892 892
893 void ServiceWorkerVersion::OnReportException( 893 void ServiceWorkerVersion::OnReportException(
894 const base::string16& error_message, 894 const base::string16& error_message,
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
1419 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1419 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1420 if (running_status() != RUNNING) 1420 if (running_status() != RUNNING)
1421 return; 1421 return;
1422 1422
1423 embedded_worker_->SendMessage( 1423 embedded_worker_->SendMessage(
1424 ServiceWorkerMsg_DidGetClients(request_id, clients)); 1424 ServiceWorkerMsg_DidGetClients(request_id, clients));
1425 } 1425 }
1426 1426
1427 void ServiceWorkerVersion::StartTimeoutTimer() { 1427 void ServiceWorkerVersion::StartTimeoutTimer() {
1428 DCHECK(!timeout_timer_.IsRunning()); 1428 DCHECK(!timeout_timer_.IsRunning());
1429
1430 if (embedded_worker_->devtools_attached())
1431 ClearTick(&start_time_);
1432 else
1433 RestartTick(&start_time_);
1434 start_callbacks_.push_back(
1435 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult,
1436 weak_factory_.GetWeakPtr()));
1437
1429 ClearTick(&idle_time_); 1438 ClearTick(&idle_time_);
1430 ClearTick(&ping_time_); 1439 ClearTick(&ping_time_);
1431 ping_timed_out_ = false; 1440 ping_state_ = NOT_PINGING;
1441
1432 timeout_timer_.Start(FROM_HERE, 1442 timeout_timer_.Start(FROM_HERE,
1433 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds), 1443 base::TimeDelta::FromSeconds(kTimeoutTimerDelaySeconds),
1434 this, &ServiceWorkerVersion::OnTimeoutTimer); 1444 this, &ServiceWorkerVersion::OnTimeoutTimer);
1435 } 1445 }
1436 1446
1437 void ServiceWorkerVersion::StopTimeoutTimer() { 1447 void ServiceWorkerVersion::StopTimeoutTimer() {
1438 timeout_timer_.Stop(); 1448 timeout_timer_.Stop();
1439 } 1449 }
1440 1450
1441 void ServiceWorkerVersion::OnTimeoutTimer() { 1451 void ServiceWorkerVersion::OnTimeoutTimer() {
1452 DCHECK(running_status() == STARTING || running_status() == RUNNING ||
1453 running_status() == STOPPING)
1454 << running_status();
1455
1456 // Starting a worker hasn't finished within a certain period.
1457 if (GetTickDuration(start_time_) >
1458 base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) {
1459 DCHECK_NE(RUNNING, running_status());
1460 scoped_refptr<ServiceWorkerVersion> protect(this);
1461 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
1462 if (running_status() == STARTING)
1463 embedded_worker_->Stop();
1464 return;
1465 }
1466
1467 // This check occurs after the start_time_ timeout check, since in that case
1468 // the start callbacks should fail with ERROR_TIMEOUT. In the other timeout
1469 // checks, there's nothing more to do as the worker is already stopping.
1442 if (running_status() == STOPPING) 1470 if (running_status() == STOPPING)
1443 return; 1471 return;
1444 DCHECK(running_status() == STARTING || running_status() == RUNNING); 1472
1473 // The worker has been idle for longer than a certain period.
1445 if (GetTickDuration(idle_time_) > 1474 if (GetTickDuration(idle_time_) >
1446 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) { 1475 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) {
1447 StopWorkerIfIdle(); 1476 StopWorkerIfIdle();
1448 StopTimeoutTimer();
1449 return; 1477 return;
1450 } 1478 }
1479
1480 // The worker hasn't responded to ping within a certain period.
1451 if (GetTickDuration(ping_time_) > 1481 if (GetTickDuration(ping_time_) >
1452 base::TimeDelta::FromSeconds(kPingTimeoutSeconds)) { 1482 base::TimeDelta::FromSeconds(kPingTimeoutSeconds)) {
1453 OnPingTimeout(); 1483 OnPingTimeout();
1454 StopTimeoutTimer();
1455 return; 1484 return;
1456 } 1485 }
1457 1486
1458 if (ping_time_.is_null()) 1487 if (ping_state_ == PINGING && ping_time_.is_null())
1459 PingWorker(); 1488 PingWorker();
1460 } 1489 }
1461 1490
1462 void ServiceWorkerVersion::PingWorker() { 1491 void ServiceWorkerVersion::PingWorker() {
1463 DCHECK(running_status() == STARTING || running_status() == RUNNING); 1492 DCHECK(running_status() == STARTING || running_status() == RUNNING);
1493 DCHECK_EQ(PINGING, ping_state_);
1464 ServiceWorkerStatusCode status = 1494 ServiceWorkerStatusCode status =
1465 embedded_worker_->SendMessage(ServiceWorkerMsg_Ping()); 1495 embedded_worker_->SendMessage(ServiceWorkerMsg_Ping());
1466 if (status != SERVICE_WORKER_OK) { 1496 if (status != SERVICE_WORKER_OK) {
1467 // TODO(falken): Maybe try resending Ping a few times first? 1497 // TODO(falken): Maybe try resending Ping a few times first?
1468 ping_timed_out_ = true; 1498 ping_state_ = PING_TIMED_OUT;
1469 StopWorkerIfIdle(); 1499 StopWorkerIfIdle();
1470 return; 1500 return;
1471 } 1501 }
1472 RestartTick(&ping_time_); 1502 RestartTick(&ping_time_);
1473 } 1503 }
1474 1504
1475 void ServiceWorkerVersion::OnPingTimeout() { 1505 void ServiceWorkerVersion::OnPingTimeout() {
1476 DCHECK(running_status() == STARTING || running_status() == RUNNING); 1506 DCHECK(running_status() == STARTING || running_status() == RUNNING);
1477 ping_timed_out_ = true; 1507 ping_state_ = PING_TIMED_OUT;
1478 // TODO(falken): Show a message to the developer that the SW was stopped due 1508 // TODO(falken): Show a message to the developer that the SW was stopped due
1479 // to timeout (crbug.com/457968). Also, change the error code to 1509 // to timeout (crbug.com/457968). Also, change the error code to
1480 // SERVICE_WORKER_ERROR_TIMEOUT. 1510 // SERVICE_WORKER_ERROR_TIMEOUT.
1481 StopWorkerIfIdle(); 1511 StopWorkerIfIdle();
1482 } 1512 }
1483 1513
1484 void ServiceWorkerVersion::StopWorkerIfIdle() { 1514 void ServiceWorkerVersion::StopWorkerIfIdle() {
1485 if (HasInflightRequests() && !ping_timed_out_) 1515 if (HasInflightRequests() && ping_state_ != PING_TIMED_OUT)
1486 return; 1516 return;
1487 if (running_status() == STOPPED || running_status() == STOPPING || 1517 if (running_status() == STOPPED || running_status() == STOPPING ||
1488 !stop_callbacks_.empty()) { 1518 !stop_callbacks_.empty()) {
1489 return; 1519 return;
1490 } 1520 }
1491 1521
1492 // TODO(falken): We may need to handle StopIfIdle failure and 1522 // TODO(falken): We may need to handle StopIfIdle failure and
1493 // forcibly fail pending callbacks so no one is stuck waiting 1523 // forcibly fail pending callbacks so no one is stuck waiting
1494 // for the worker. 1524 // for the worker.
1495 embedded_worker_->StopIfIdle(); 1525 embedded_worker_->StopIfIdle();
1496 } 1526 }
1497 1527
1498 bool ServiceWorkerVersion::HasInflightRequests() const { 1528 bool ServiceWorkerVersion::HasInflightRequests() const {
1499 return 1529 return
1500 !activate_callbacks_.IsEmpty() || 1530 !activate_callbacks_.IsEmpty() ||
1501 !install_callbacks_.IsEmpty() || 1531 !install_callbacks_.IsEmpty() ||
1502 !fetch_callbacks_.IsEmpty() || 1532 !fetch_callbacks_.IsEmpty() ||
1503 !sync_callbacks_.IsEmpty() || 1533 !sync_callbacks_.IsEmpty() ||
1504 !notification_click_callbacks_.IsEmpty() || 1534 !notification_click_callbacks_.IsEmpty() ||
1505 !push_callbacks_.IsEmpty() || 1535 !push_callbacks_.IsEmpty() ||
1506 !geofencing_callbacks_.IsEmpty() || 1536 !geofencing_callbacks_.IsEmpty() ||
1507 !cross_origin_connect_callbacks_.IsEmpty() || 1537 !cross_origin_connect_callbacks_.IsEmpty() ||
1508 !streaming_url_request_jobs_.empty(); 1538 !streaming_url_request_jobs_.empty();
1509 } 1539 }
1510 1540
1511 void ServiceWorkerVersion::ScheduleStartWorkerTimeout() {
1512 DCHECK(!start_worker_timeout_timer_.IsRunning());
1513 start_timing_ = embedded_worker_->devtools_attached()
1514 ? base::TimeTicks()
1515 : base::TimeTicks::Now();
1516 start_callbacks_.push_back(
1517 base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult,
1518 weak_factory_.GetWeakPtr()));
1519 start_worker_timeout_timer_.Start(
1520 FROM_HERE, base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes),
1521 base::Bind(&ServiceWorkerVersion::OnStartWorkerTimeout,
1522 weak_factory_.GetWeakPtr()));
1523 }
1524
1525 void ServiceWorkerVersion::OnStartWorkerTimeout() {
1526 DCHECK(running_status() == STARTING || running_status() == STOPPING)
1527 << running_status();
1528
1529 if (embedded_worker_->devtools_attached()) {
1530 start_worker_timeout_timer_.Stop();
1531 return;
1532 }
1533
1534 scoped_refptr<ServiceWorkerVersion> protect(this);
1535 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT);
1536 if (running_status() == STARTING)
1537 embedded_worker_->Stop();
1538 }
1539
1540 void ServiceWorkerVersion::RecordStartWorkerResult( 1541 void ServiceWorkerVersion::RecordStartWorkerResult(
1541 ServiceWorkerStatusCode status) { 1542 ServiceWorkerStatusCode status) {
1542 start_worker_timeout_timer_.Stop();
1543
1544 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status, 1543 UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status,
1545 SERVICE_WORKER_ERROR_MAX_VALUE); 1544 SERVICE_WORKER_ERROR_MAX_VALUE);
1546 if (status == SERVICE_WORKER_OK && !start_timing_.is_null()) { 1545 if (status == SERVICE_WORKER_OK && !start_time_.is_null()) {
1547 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", 1546 UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time",
1548 GetTickDuration(start_timing_)); 1547 GetTickDuration(start_time_));
1549 } 1548 }
1550 1549
1550 ClearTick(&start_time_);
1551 if (status != SERVICE_WORKER_ERROR_TIMEOUT) 1551 if (status != SERVICE_WORKER_ERROR_TIMEOUT)
1552 return; 1552 return;
1553 EmbeddedWorkerInstance::StartingPhase phase = 1553 EmbeddedWorkerInstance::StartingPhase phase =
1554 EmbeddedWorkerInstance::NOT_STARTING; 1554 EmbeddedWorkerInstance::NOT_STARTING;
1555 EmbeddedWorkerInstance::Status running_status = embedded_worker_->status(); 1555 EmbeddedWorkerInstance::Status running_status = embedded_worker_->status();
1556 // Build an artifical JavaScript exception to show in the ServiceWorker 1556 // Build an artifical JavaScript exception to show in the ServiceWorker
1557 // log for developers; it's not user-facing so it's not a localized resource. 1557 // log for developers; it's not user-facing so it's not a localized resource.
1558 std::string message = "ServiceWorker startup timed out. "; 1558 std::string message = "ServiceWorker startup timed out. ";
1559 if (running_status != EmbeddedWorkerInstance::STARTING) { 1559 if (running_status != EmbeddedWorkerInstance::STARTING) {
1560 message.append("The worker had unexpected status: "); 1560 message.append("The worker had unexpected status: ");
(...skipping 29 matching lines...) Expand all
1590 int request_id) { 1590 int request_id) {
1591 callbacks->Remove(request_id); 1591 callbacks->Remove(request_id);
1592 if (is_doomed_) { 1592 if (is_doomed_) {
1593 // The stop should be already scheduled, but try to stop immediately, in 1593 // The stop should be already scheduled, but try to stop immediately, in
1594 // order to release worker resources soon. 1594 // order to release worker resources soon.
1595 StopWorkerIfIdle(); 1595 StopWorkerIfIdle();
1596 } 1596 }
1597 } 1597 }
1598 1598
1599 } // namespace content 1599 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698