| OLD | NEW |
| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 template <typename IDMAP, typename... Params> | 85 template <typename IDMAP, typename... Params> |
| 86 void RunIDMapCallbacks(IDMAP* callbacks, const Params&... params) { | 86 void RunIDMapCallbacks(IDMAP* callbacks, const Params&... params) { |
| 87 typename IDMAP::iterator iter(callbacks); | 87 typename IDMAP::iterator iter(callbacks); |
| 88 while (!iter.IsAtEnd()) { | 88 while (!iter.IsAtEnd()) { |
| 89 iter.GetCurrentValue()->Run(params...); | 89 iter.GetCurrentValue()->Run(params...); |
| 90 iter.Advance(); | 90 iter.Advance(); |
| 91 } | 91 } |
| 92 callbacks->Clear(); | 92 callbacks->Clear(); |
| 93 } | 93 } |
| 94 | 94 |
| 95 template <typename CallbackType, typename... Params> |
| 96 bool RunIDMapCallback(IDMap<CallbackType, IDMapOwnPointer>* callbacks, |
| 97 int request_id, |
| 98 const Params&... params) { |
| 99 CallbackType* callback = callbacks->Lookup(request_id); |
| 100 if (!callback) |
| 101 return false; |
| 102 |
| 103 callback->Run(params...); |
| 104 callbacks->Remove(request_id); |
| 105 return true; |
| 106 } |
| 107 |
| 95 void RunStartWorkerCallback( | 108 void RunStartWorkerCallback( |
| 96 const StatusCallback& callback, | 109 const StatusCallback& callback, |
| 97 scoped_refptr<ServiceWorkerRegistration> protect, | 110 scoped_refptr<ServiceWorkerRegistration> protect, |
| 98 ServiceWorkerStatusCode status) { | 111 ServiceWorkerStatusCode status) { |
| 99 callback.Run(status); | 112 callback.Run(status); |
| 100 } | 113 } |
| 101 | 114 |
| 102 // A callback adapter to start a |task| after StartWorker. | 115 // A callback adapter to start a |task| after StartWorker. |
| 103 void RunTaskAfterStartWorker( | 116 void RunTaskAfterStartWorker( |
| 104 base::WeakPtr<ServiceWorkerVersion> version, | 117 base::WeakPtr<ServiceWorkerVersion> version, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 135 // Transfering the message ports failed, so destroy the ports. | 148 // Transfering the message ports failed, so destroy the ports. |
| 136 for (const TransferredMessagePort& port : sent_message_ports) { | 149 for (const TransferredMessagePort& port : sent_message_ports) { |
| 137 MessagePortService::GetInstance()->ClosePort(port.id); | 150 MessagePortService::GetInstance()->ClosePort(port.id); |
| 138 } | 151 } |
| 139 callback.Run(status); | 152 callback.Run(status); |
| 140 } | 153 } |
| 141 | 154 |
| 142 void RunErrorCrossOriginConnectCallback( | 155 void RunErrorCrossOriginConnectCallback( |
| 143 const ServiceWorkerVersion::CrossOriginConnectCallback& callback, | 156 const ServiceWorkerVersion::CrossOriginConnectCallback& callback, |
| 144 ServiceWorkerStatusCode status) { | 157 ServiceWorkerStatusCode status) { |
| 145 callback.Run(status, false); | 158 callback.Run(status, false /* accept_connection */); |
| 146 } | 159 } |
| 147 | 160 |
| 148 using WindowOpenedCallback = base::Callback<void(int, int)>; | 161 using WindowOpenedCallback = base::Callback<void(int, int)>; |
| 149 | 162 |
| 150 // The WindowOpenedObserver class is a WebContentsObserver that will wait for a | 163 // The WindowOpenedObserver class is a WebContentsObserver that will wait for a |
| 151 // new Window's WebContents to be initialized, run the |callback| passed to its | 164 // new Window's WebContents to be initialized, run the |callback| passed to its |
| 152 // constructor then self destroy. | 165 // constructor then self destroy. |
| 153 // The callback will receive the process and frame ids. If something went wrong | 166 // The callback will receive the process and frame ids. If something went wrong |
| 154 // those will be (kInvalidUniqueID, MSG_ROUTING_NONE). | 167 // those will be (kInvalidUniqueID, MSG_ROUTING_NONE). |
| 155 // The callback will be called in the IO thread. | 168 // The callback will be called in the IO thread. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 clients.push_back(info); | 310 clients.push_back(info); |
| 298 } | 311 } |
| 299 | 312 |
| 300 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 313 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 301 base::Bind(callback, clients)); | 314 base::Bind(callback, clients)); |
| 302 } | 315 } |
| 303 | 316 |
| 304 } // namespace | 317 } // namespace |
| 305 | 318 |
| 306 const int ServiceWorkerVersion::kStartWorkerTimeoutMinutes = 5; | 319 const int ServiceWorkerVersion::kStartWorkerTimeoutMinutes = 5; |
| 320 const int ServiceWorkerVersion::kRequestTimeoutMinutes = 5; |
| 307 | 321 |
| 308 ServiceWorkerVersion::ServiceWorkerVersion( | 322 ServiceWorkerVersion::ServiceWorkerVersion( |
| 309 ServiceWorkerRegistration* registration, | 323 ServiceWorkerRegistration* registration, |
| 310 const GURL& script_url, | 324 const GURL& script_url, |
| 311 int64 version_id, | 325 int64 version_id, |
| 312 base::WeakPtr<ServiceWorkerContextCore> context) | 326 base::WeakPtr<ServiceWorkerContextCore> context) |
| 313 : version_id_(version_id), | 327 : version_id_(version_id), |
| 314 registration_id_(kInvalidServiceWorkerVersionId), | 328 registration_id_(kInvalidServiceWorkerVersionId), |
| 315 script_url_(script_url), | 329 script_url_(script_url), |
| 316 status_(NEW), | 330 status_(NEW), |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 base::Bind(&self::DispatchFetchEvent, | 543 base::Bind(&self::DispatchFetchEvent, |
| 530 weak_factory_.GetWeakPtr(), | 544 weak_factory_.GetWeakPtr(), |
| 531 request, | 545 request, |
| 532 prepare_callback, | 546 prepare_callback, |
| 533 fetch_callback))); | 547 fetch_callback))); |
| 534 return; | 548 return; |
| 535 } | 549 } |
| 536 | 550 |
| 537 prepare_callback.Run(); | 551 prepare_callback.Run(); |
| 538 | 552 |
| 539 int request_id = fetch_callbacks_.Add(new FetchCallback(fetch_callback)); | 553 int request_id = AddRequest(fetch_callback, &fetch_callbacks_, REQUEST_FETCH); |
| 540 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( | 554 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( |
| 541 ServiceWorkerMsg_FetchEvent(request_id, request)); | 555 ServiceWorkerMsg_FetchEvent(request_id, request)); |
| 542 if (status != SERVICE_WORKER_OK) { | 556 if (status != SERVICE_WORKER_OK) { |
| 543 fetch_callbacks_.Remove(request_id); | 557 fetch_callbacks_.Remove(request_id); |
| 544 RunSoon(base::Bind(&RunErrorFetchCallback, | 558 RunSoon(base::Bind(&RunErrorFetchCallback, |
| 545 fetch_callback, | 559 fetch_callback, |
| 546 SERVICE_WORKER_ERROR_FAILED)); | 560 SERVICE_WORKER_ERROR_FAILED)); |
| 547 } | 561 } |
| 548 } | 562 } |
| 549 | 563 |
| 550 void ServiceWorkerVersion::DispatchSyncEvent(const StatusCallback& callback) { | 564 void ServiceWorkerVersion::DispatchSyncEvent(const StatusCallback& callback) { |
| 551 DCHECK_EQ(ACTIVATED, status()) << status(); | 565 DCHECK_EQ(ACTIVATED, status()) << status(); |
| 552 | 566 |
| 553 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 567 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 554 switches::kEnableServiceWorkerSync)) { | 568 switches::kEnableServiceWorkerSync)) { |
| 555 callback.Run(SERVICE_WORKER_ERROR_ABORT); | 569 callback.Run(SERVICE_WORKER_ERROR_ABORT); |
| 556 return; | 570 return; |
| 557 } | 571 } |
| 558 | 572 |
| 559 if (running_status() != RUNNING) { | 573 if (running_status() != RUNNING) { |
| 560 // Schedule calling this method after starting the worker. | 574 // Schedule calling this method after starting the worker. |
| 561 StartWorker(base::Bind(&RunTaskAfterStartWorker, | 575 StartWorker(base::Bind(&RunTaskAfterStartWorker, |
| 562 weak_factory_.GetWeakPtr(), callback, | 576 weak_factory_.GetWeakPtr(), callback, |
| 563 base::Bind(&self::DispatchSyncEvent, | 577 base::Bind(&self::DispatchSyncEvent, |
| 564 weak_factory_.GetWeakPtr(), | 578 weak_factory_.GetWeakPtr(), |
| 565 callback))); | 579 callback))); |
| 566 return; | 580 return; |
| 567 } | 581 } |
| 568 | 582 |
| 569 int request_id = sync_callbacks_.Add(new StatusCallback(callback)); | 583 int request_id = AddRequest(callback, &sync_callbacks_, REQUEST_SYNC); |
| 570 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( | 584 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( |
| 571 ServiceWorkerMsg_SyncEvent(request_id)); | 585 ServiceWorkerMsg_SyncEvent(request_id)); |
| 572 if (status != SERVICE_WORKER_OK) { | 586 if (status != SERVICE_WORKER_OK) { |
| 573 sync_callbacks_.Remove(request_id); | 587 sync_callbacks_.Remove(request_id); |
| 574 RunSoon(base::Bind(callback, status)); | 588 RunSoon(base::Bind(callback, status)); |
| 575 } | 589 } |
| 576 } | 590 } |
| 577 | 591 |
| 578 void ServiceWorkerVersion::DispatchNotificationClickEvent( | 592 void ServiceWorkerVersion::DispatchNotificationClickEvent( |
| 579 const StatusCallback& callback, | 593 const StatusCallback& callback, |
| 580 const std::string& notification_id, | 594 const std::string& notification_id, |
| 581 const PlatformNotificationData& notification_data) { | 595 const PlatformNotificationData& notification_data) { |
| 582 DCHECK_EQ(ACTIVATED, status()) << status(); | 596 DCHECK_EQ(ACTIVATED, status()) << status(); |
| 583 if (running_status() != RUNNING) { | 597 if (running_status() != RUNNING) { |
| 584 // Schedule calling this method after starting the worker. | 598 // Schedule calling this method after starting the worker. |
| 585 StartWorker(base::Bind(&RunTaskAfterStartWorker, | 599 StartWorker(base::Bind(&RunTaskAfterStartWorker, |
| 586 weak_factory_.GetWeakPtr(), callback, | 600 weak_factory_.GetWeakPtr(), callback, |
| 587 base::Bind(&self::DispatchNotificationClickEvent, | 601 base::Bind(&self::DispatchNotificationClickEvent, |
| 588 weak_factory_.GetWeakPtr(), | 602 weak_factory_.GetWeakPtr(), |
| 589 callback, notification_id, | 603 callback, notification_id, |
| 590 notification_data))); | 604 notification_data))); |
| 591 return; | 605 return; |
| 592 } | 606 } |
| 593 | 607 |
| 594 int request_id = | 608 int request_id = AddRequest(callback, ¬ification_click_callbacks_, |
| 595 notification_click_callbacks_.Add(new StatusCallback(callback)); | 609 REQUEST_NOTIFICATION_CLICK); |
| 596 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( | 610 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( |
| 597 ServiceWorkerMsg_NotificationClickEvent(request_id, | 611 ServiceWorkerMsg_NotificationClickEvent(request_id, |
| 598 notification_id, | 612 notification_id, |
| 599 notification_data)); | 613 notification_data)); |
| 600 if (status != SERVICE_WORKER_OK) { | 614 if (status != SERVICE_WORKER_OK) { |
| 601 notification_click_callbacks_.Remove(request_id); | 615 notification_click_callbacks_.Remove(request_id); |
| 602 RunSoon(base::Bind(callback, status)); | 616 RunSoon(base::Bind(callback, status)); |
| 603 } | 617 } |
| 604 } | 618 } |
| 605 | 619 |
| 606 void ServiceWorkerVersion::DispatchPushEvent(const StatusCallback& callback, | 620 void ServiceWorkerVersion::DispatchPushEvent(const StatusCallback& callback, |
| 607 const std::string& data) { | 621 const std::string& data) { |
| 608 DCHECK_EQ(ACTIVATED, status()) << status(); | 622 DCHECK_EQ(ACTIVATED, status()) << status(); |
| 609 if (running_status() != RUNNING) { | 623 if (running_status() != RUNNING) { |
| 610 // Schedule calling this method after starting the worker. | 624 // Schedule calling this method after starting the worker. |
| 611 StartWorker(base::Bind(&RunTaskAfterStartWorker, | 625 StartWorker(base::Bind(&RunTaskAfterStartWorker, |
| 612 weak_factory_.GetWeakPtr(), callback, | 626 weak_factory_.GetWeakPtr(), callback, |
| 613 base::Bind(&self::DispatchPushEvent, | 627 base::Bind(&self::DispatchPushEvent, |
| 614 weak_factory_.GetWeakPtr(), | 628 weak_factory_.GetWeakPtr(), |
| 615 callback, data))); | 629 callback, data))); |
| 616 return; | 630 return; |
| 617 } | 631 } |
| 618 | 632 |
| 619 int request_id = push_callbacks_.Add(new StatusCallback(callback)); | 633 int request_id = AddRequest(callback, &push_callbacks_, REQUEST_PUSH); |
| 620 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( | 634 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( |
| 621 ServiceWorkerMsg_PushEvent(request_id, data)); | 635 ServiceWorkerMsg_PushEvent(request_id, data)); |
| 622 if (status != SERVICE_WORKER_OK) { | 636 if (status != SERVICE_WORKER_OK) { |
| 623 push_callbacks_.Remove(request_id); | 637 push_callbacks_.Remove(request_id); |
| 624 RunSoon(base::Bind(callback, status)); | 638 RunSoon(base::Bind(callback, status)); |
| 625 } | 639 } |
| 626 } | 640 } |
| 627 | 641 |
| 628 void ServiceWorkerVersion::DispatchGeofencingEvent( | 642 void ServiceWorkerVersion::DispatchGeofencingEvent( |
| 629 const StatusCallback& callback, | 643 const StatusCallback& callback, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 645 callback, | 659 callback, |
| 646 base::Bind(&self::DispatchGeofencingEvent, | 660 base::Bind(&self::DispatchGeofencingEvent, |
| 647 weak_factory_.GetWeakPtr(), | 661 weak_factory_.GetWeakPtr(), |
| 648 callback, | 662 callback, |
| 649 event_type, | 663 event_type, |
| 650 region_id, | 664 region_id, |
| 651 region))); | 665 region))); |
| 652 return; | 666 return; |
| 653 } | 667 } |
| 654 | 668 |
| 655 int request_id = geofencing_callbacks_.Add(new StatusCallback(callback)); | 669 int request_id = |
| 670 AddRequest(callback, &geofencing_callbacks_, REQUEST_GEOFENCING); |
| 656 ServiceWorkerStatusCode status = | 671 ServiceWorkerStatusCode status = |
| 657 embedded_worker_->SendMessage(ServiceWorkerMsg_GeofencingEvent( | 672 embedded_worker_->SendMessage(ServiceWorkerMsg_GeofencingEvent( |
| 658 request_id, event_type, region_id, region)); | 673 request_id, event_type, region_id, region)); |
| 659 if (status != SERVICE_WORKER_OK) { | 674 if (status != SERVICE_WORKER_OK) { |
| 660 geofencing_callbacks_.Remove(request_id); | 675 geofencing_callbacks_.Remove(request_id); |
| 661 RunSoon(base::Bind(callback, status)); | 676 RunSoon(base::Bind(callback, status)); |
| 662 } | 677 } |
| 663 } | 678 } |
| 664 | 679 |
| 665 void ServiceWorkerVersion::DispatchCrossOriginConnectEvent( | 680 void ServiceWorkerVersion::DispatchCrossOriginConnectEvent( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 676 if (running_status() != RUNNING) { | 691 if (running_status() != RUNNING) { |
| 677 // Schedule calling this method after starting the worker. | 692 // Schedule calling this method after starting the worker. |
| 678 StartWorker( | 693 StartWorker( |
| 679 base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), | 694 base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), |
| 680 base::Bind(&RunErrorCrossOriginConnectCallback, callback), | 695 base::Bind(&RunErrorCrossOriginConnectCallback, callback), |
| 681 base::Bind(&self::DispatchCrossOriginConnectEvent, | 696 base::Bind(&self::DispatchCrossOriginConnectEvent, |
| 682 weak_factory_.GetWeakPtr(), callback, client))); | 697 weak_factory_.GetWeakPtr(), callback, client))); |
| 683 return; | 698 return; |
| 684 } | 699 } |
| 685 | 700 |
| 686 int request_id = cross_origin_connect_callbacks_.Add( | 701 int request_id = AddRequest(callback, &cross_origin_connect_callbacks_, |
| 687 new CrossOriginConnectCallback(callback)); | 702 REQUEST_CROSS_ORIGIN_CONNECT); |
| 688 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( | 703 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( |
| 689 ServiceWorkerMsg_CrossOriginConnectEvent(request_id, client)); | 704 ServiceWorkerMsg_CrossOriginConnectEvent(request_id, client)); |
| 690 if (status != SERVICE_WORKER_OK) { | 705 if (status != SERVICE_WORKER_OK) { |
| 691 cross_origin_connect_callbacks_.Remove(request_id); | 706 cross_origin_connect_callbacks_.Remove(request_id); |
| 692 RunSoon(base::Bind(callback, status, false)); | 707 RunSoon(base::Bind(callback, status, false)); |
| 693 } | 708 } |
| 694 } | 709 } |
| 695 | 710 |
| 696 void ServiceWorkerVersion::DispatchCrossOriginMessageEvent( | 711 void ServiceWorkerVersion::DispatchCrossOriginMessageEvent( |
| 697 const NavigatorConnectClient& client, | 712 const NavigatorConnectClient& client, |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 if (is_doomed_) | 788 if (is_doomed_) |
| 774 return; | 789 return; |
| 775 is_doomed_ = true; | 790 is_doomed_ = true; |
| 776 if (!HasControllee()) | 791 if (!HasControllee()) |
| 777 DoomInternal(); | 792 DoomInternal(); |
| 778 } | 793 } |
| 779 | 794 |
| 780 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { | 795 void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { |
| 781 embedded_worker()->set_devtools_attached(attached); | 796 embedded_worker()->set_devtools_attached(attached); |
| 782 if (attached) { | 797 if (attached) { |
| 798 // TODO(falken): Canceling the timeouts when debugging could cause |
| 799 // heisenbugs; we should instead run them as normal show an educational |
| 800 // message in DevTools when they occur. crbug.com/470419 |
| 801 |
| 783 // Don't record the startup time metric once DevTools is attached. | 802 // Don't record the startup time metric once DevTools is attached. |
| 784 ClearTick(&start_time_); | 803 ClearTick(&start_time_); |
| 785 skip_recording_startup_time_ = true; | 804 skip_recording_startup_time_ = true; |
| 805 |
| 806 // Cancel request timeouts. |
| 807 SetAllRequestTimes(base::TimeTicks()); |
| 786 return; | 808 return; |
| 787 } | 809 } |
| 788 if (!start_callbacks_.empty()) { | 810 if (!start_callbacks_.empty()) { |
| 789 // Reactivate the timer for start timeout. | 811 // Reactivate the timer for start timeout. |
| 790 DCHECK(timeout_timer_.IsRunning()); | 812 DCHECK(timeout_timer_.IsRunning()); |
| 791 DCHECK(running_status() == STARTING || running_status() == STOPPING) | 813 DCHECK(running_status() == STARTING || running_status() == STOPPING) |
| 792 << running_status(); | 814 << running_status(); |
| 793 RestartTick(&start_time_); | 815 RestartTick(&start_time_); |
| 794 } | 816 } |
| 817 |
| 818 // Reactivate request timeouts. |
| 819 SetAllRequestTimes(base::TimeTicks::Now()); |
| 795 } | 820 } |
| 796 | 821 |
| 797 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( | 822 void ServiceWorkerVersion::SetMainScriptHttpResponseInfo( |
| 798 const net::HttpResponseInfo& http_info) { | 823 const net::HttpResponseInfo& http_info) { |
| 799 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); | 824 main_script_http_info_.reset(new net::HttpResponseInfo(http_info)); |
| 800 } | 825 } |
| 801 | 826 |
| 802 const net::HttpResponseInfo* | 827 const net::HttpResponseInfo* |
| 803 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { | 828 ServiceWorkerVersion::GetMainScriptHttpResponseInfo() { |
| 804 return main_script_http_info_.get(); | 829 return main_script_http_info_.get(); |
| 805 } | 830 } |
| 806 | 831 |
| 832 ServiceWorkerVersion::RequestInfo::RequestInfo(int id, RequestType type) |
| 833 : id(id), type(type), time(base::TimeTicks::Now()) { |
| 834 } |
| 835 |
| 836 ServiceWorkerVersion::RequestInfo::~RequestInfo() { |
| 837 } |
| 838 |
| 807 void ServiceWorkerVersion::OnScriptLoaded() { | 839 void ServiceWorkerVersion::OnScriptLoaded() { |
| 808 DCHECK_EQ(STARTING, running_status()); | 840 DCHECK_EQ(STARTING, running_status()); |
| 809 // Activate ping/pong now that JavaScript execution will start. | 841 // Activate ping/pong now that JavaScript execution will start. |
| 810 ping_state_ = PINGING; | 842 ping_state_ = PINGING; |
| 811 } | 843 } |
| 812 | 844 |
| 813 void ServiceWorkerVersion::OnStarting() { | 845 void ServiceWorkerVersion::OnStarting() { |
| 814 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); | 846 FOR_EACH_OBSERVER(Listener, listeners_, OnRunningStateChanged(this)); |
| 815 } | 847 } |
| 816 | 848 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 ServiceWorkerStatusCode status) { | 991 ServiceWorkerStatusCode status) { |
| 960 if (status != SERVICE_WORKER_OK) | 992 if (status != SERVICE_WORKER_OK) |
| 961 RunCallbacks(this, &start_callbacks_, status); | 993 RunCallbacks(this, &start_callbacks_, status); |
| 962 } | 994 } |
| 963 | 995 |
| 964 void ServiceWorkerVersion::DispatchInstallEventAfterStartWorker( | 996 void ServiceWorkerVersion::DispatchInstallEventAfterStartWorker( |
| 965 const StatusCallback& callback) { | 997 const StatusCallback& callback) { |
| 966 DCHECK_EQ(RUNNING, running_status()) | 998 DCHECK_EQ(RUNNING, running_status()) |
| 967 << "Worker stopped too soon after it was started."; | 999 << "Worker stopped too soon after it was started."; |
| 968 | 1000 |
| 969 int request_id = install_callbacks_.Add(new StatusCallback(callback)); | 1001 int request_id = AddRequest(callback, &install_callbacks_, REQUEST_INSTALL); |
| 970 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( | 1002 ServiceWorkerStatusCode status = embedded_worker_->SendMessage( |
| 971 ServiceWorkerMsg_InstallEvent(request_id)); | 1003 ServiceWorkerMsg_InstallEvent(request_id)); |
| 972 if (status != SERVICE_WORKER_OK) { | 1004 if (status != SERVICE_WORKER_OK) { |
| 973 install_callbacks_.Remove(request_id); | 1005 install_callbacks_.Remove(request_id); |
| 974 RunSoon(base::Bind(callback, status)); | 1006 RunSoon(base::Bind(callback, status)); |
| 975 } | 1007 } |
| 976 } | 1008 } |
| 977 | 1009 |
| 978 void ServiceWorkerVersion::DispatchActivateEventAfterStartWorker( | 1010 void ServiceWorkerVersion::DispatchActivateEventAfterStartWorker( |
| 979 const StatusCallback& callback) { | 1011 const StatusCallback& callback) { |
| 980 DCHECK_EQ(RUNNING, running_status()) | 1012 DCHECK_EQ(RUNNING, running_status()) |
| 981 << "Worker stopped too soon after it was started."; | 1013 << "Worker stopped too soon after it was started."; |
| 982 | 1014 |
| 983 int request_id = activate_callbacks_.Add(new StatusCallback(callback)); | 1015 int request_id = AddRequest(callback, &activate_callbacks_, REQUEST_ACTIVATE); |
| 984 ServiceWorkerStatusCode status = | 1016 ServiceWorkerStatusCode status = |
| 985 embedded_worker_->SendMessage(ServiceWorkerMsg_ActivateEvent(request_id)); | 1017 embedded_worker_->SendMessage(ServiceWorkerMsg_ActivateEvent(request_id)); |
| 986 if (status != SERVICE_WORKER_OK) { | 1018 if (status != SERVICE_WORKER_OK) { |
| 987 activate_callbacks_.Remove(request_id); | 1019 activate_callbacks_.Remove(request_id); |
| 988 RunSoon(base::Bind(callback, status)); | 1020 RunSoon(base::Bind(callback, status)); |
| 989 } | 1021 } |
| 990 } | 1022 } |
| 991 | 1023 |
| 992 void ServiceWorkerVersion::OnGetClients( | 1024 void ServiceWorkerVersion::OnGetClients( |
| 993 int request_id, | 1025 int request_id, |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) { | 1566 base::TimeDelta::FromMinutes(kStartWorkerTimeoutMinutes)) { |
| 1535 DCHECK(running_status() == STARTING || running_status() == STOPPING) | 1567 DCHECK(running_status() == STARTING || running_status() == STOPPING) |
| 1536 << running_status(); | 1568 << running_status(); |
| 1537 scoped_refptr<ServiceWorkerVersion> protect(this); | 1569 scoped_refptr<ServiceWorkerVersion> protect(this); |
| 1538 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); | 1570 RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_ERROR_TIMEOUT); |
| 1539 if (running_status() == STARTING) | 1571 if (running_status() == STARTING) |
| 1540 embedded_worker_->Stop(); | 1572 embedded_worker_->Stop(); |
| 1541 return; | 1573 return; |
| 1542 } | 1574 } |
| 1543 | 1575 |
| 1544 // This check occurs after the start_time_ timeout check, since in that case | 1576 // Requests have not finished within a certain period. |
| 1545 // the start callbacks should fail with ERROR_TIMEOUT. In the other timeout | 1577 bool request_timed_out = false; |
| 1546 // checks, there's nothing more to do as the worker is already stopping. | 1578 while (!requests_.empty()) { |
| 1579 RequestInfo info = requests_.front(); |
| 1580 if (GetTickDuration(info.time) < |
| 1581 base::TimeDelta::FromMinutes(kRequestTimeoutMinutes)) |
| 1582 break; |
| 1583 if (OnRequestTimeout(info)) |
| 1584 request_timed_out = true; |
| 1585 requests_.pop(); |
| 1586 } |
| 1587 if (request_timed_out && running_status() != STOPPING) |
| 1588 embedded_worker_->Stop(); |
| 1589 |
| 1590 // For the timeouts below, there are no callbacks to timeout so there is |
| 1591 // nothing more to do if the worker is already stopping. |
| 1547 if (running_status() == STOPPING) | 1592 if (running_status() == STOPPING) |
| 1548 return; | 1593 return; |
| 1549 | 1594 |
| 1550 // The worker has been idle for longer than a certain period. | 1595 // The worker has been idle for longer than a certain period. |
| 1551 if (GetTickDuration(idle_time_) > | 1596 if (GetTickDuration(idle_time_) > |
| 1552 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) { | 1597 base::TimeDelta::FromSeconds(kIdleWorkerTimeoutSeconds)) { |
| 1553 StopWorkerIfIdle(); | 1598 StopWorkerIfIdle(); |
| 1554 return; | 1599 return; |
| 1555 } | 1600 } |
| 1556 | 1601 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1674 IDMAP* callbacks, | 1719 IDMAP* callbacks, |
| 1675 int request_id) { | 1720 int request_id) { |
| 1676 callbacks->Remove(request_id); | 1721 callbacks->Remove(request_id); |
| 1677 if (is_doomed_) { | 1722 if (is_doomed_) { |
| 1678 // The stop should be already scheduled, but try to stop immediately, in | 1723 // The stop should be already scheduled, but try to stop immediately, in |
| 1679 // order to release worker resources soon. | 1724 // order to release worker resources soon. |
| 1680 StopWorkerIfIdle(); | 1725 StopWorkerIfIdle(); |
| 1681 } | 1726 } |
| 1682 } | 1727 } |
| 1683 | 1728 |
| 1729 template <typename CallbackType> |
| 1730 int ServiceWorkerVersion::AddRequest( |
| 1731 const CallbackType& callback, |
| 1732 IDMap<CallbackType, IDMapOwnPointer>* callback_map, |
| 1733 RequestType request_type) { |
| 1734 int request_id = callback_map->Add(new CallbackType(callback)); |
| 1735 requests_.push(RequestInfo(request_id, request_type)); |
| 1736 return request_id; |
| 1737 } |
| 1738 |
| 1739 bool ServiceWorkerVersion::OnRequestTimeout(const RequestInfo& info) { |
| 1740 switch (info.type) { |
| 1741 case REQUEST_ACTIVATE: |
| 1742 return RunIDMapCallback(&activate_callbacks_, info.id, |
| 1743 SERVICE_WORKER_ERROR_TIMEOUT); |
| 1744 case REQUEST_INSTALL: |
| 1745 return RunIDMapCallback(&install_callbacks_, info.id, |
| 1746 SERVICE_WORKER_ERROR_TIMEOUT); |
| 1747 case REQUEST_FETCH: |
| 1748 return RunIDMapCallback( |
| 1749 &fetch_callbacks_, info.id, SERVICE_WORKER_ERROR_TIMEOUT, |
| 1750 /* The other args are ignored for non-OK status. */ |
| 1751 SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, ServiceWorkerResponse()); |
| 1752 case REQUEST_SYNC: |
| 1753 return RunIDMapCallback(&sync_callbacks_, info.id, |
| 1754 SERVICE_WORKER_ERROR_TIMEOUT); |
| 1755 case REQUEST_NOTIFICATION_CLICK: |
| 1756 return RunIDMapCallback(¬ification_click_callbacks_, info.id, |
| 1757 SERVICE_WORKER_ERROR_TIMEOUT); |
| 1758 case REQUEST_PUSH: |
| 1759 return RunIDMapCallback(&push_callbacks_, info.id, |
| 1760 SERVICE_WORKER_ERROR_TIMEOUT); |
| 1761 case REQUEST_GEOFENCING: |
| 1762 return RunIDMapCallback(&geofencing_callbacks_, info.id, |
| 1763 SERVICE_WORKER_ERROR_TIMEOUT); |
| 1764 case REQUEST_CROSS_ORIGIN_CONNECT: |
| 1765 return RunIDMapCallback(&cross_origin_connect_callbacks_, info.id, |
| 1766 SERVICE_WORKER_ERROR_TIMEOUT, |
| 1767 false /* accept_connection */); |
| 1768 } |
| 1769 NOTREACHED() << "Got unexpected request type: " << info.type; |
| 1770 return false; |
| 1771 } |
| 1772 |
| 1773 void ServiceWorkerVersion::SetAllRequestTimes(const base::TimeTicks& ticks) { |
| 1774 std::queue<RequestInfo> new_requests; |
| 1775 while (!requests_.empty()) { |
| 1776 RequestInfo info = requests_.front(); |
| 1777 info.time = ticks; |
| 1778 new_requests.push(info); |
| 1779 requests_.pop(); |
| 1780 } |
| 1781 requests_ = new_requests; |
| 1782 } |
| 1783 |
| 1684 } // namespace content | 1784 } // namespace content |
| OLD | NEW |