OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading |
6 | 6 |
7 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | 7 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 1561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1572 // whereas waiting for a host name to resolve implies being stuck. | 1572 // whereas waiting for a host name to resolve implies being stuck. |
1573 // | 1573 // |
1574 net::LoadState MoreInterestingLoadState(net::LoadState a, net::LoadState b) { | 1574 net::LoadState MoreInterestingLoadState(net::LoadState a, net::LoadState b) { |
1575 return (a < b) ? b : a; | 1575 return (a < b) ? b : a; |
1576 } | 1576 } |
1577 | 1577 |
1578 // Carries information about a load state change. | 1578 // Carries information about a load state change. |
1579 struct LoadInfo { | 1579 struct LoadInfo { |
1580 GURL url; | 1580 GURL url; |
1581 net::LoadState load_state; | 1581 net::LoadState load_state; |
| 1582 uint64 upload_position; |
| 1583 uint64 upload_size; |
1582 }; | 1584 }; |
1583 | 1585 |
1584 // Map from ProcessID+ViewID pair to LoadState | 1586 // Map from ProcessID+ViewID pair to LoadState |
1585 typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap; | 1587 typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap; |
1586 | 1588 |
1587 // Used to marshall calls to LoadStateChanged from the IO to UI threads. We do | 1589 // Used to marshall calls to LoadStateChanged from the IO to UI threads. We do |
1588 // them all as a single task to avoid spamming the UI thread. | 1590 // them all as a single task to avoid spamming the UI thread. |
1589 class LoadInfoUpdateTask : public Task { | 1591 class LoadInfoUpdateTask : public Task { |
1590 public: | 1592 public: |
1591 virtual void Run() { | 1593 virtual void Run() { |
1592 LoadInfoMap::const_iterator i; | 1594 LoadInfoMap::const_iterator i; |
1593 for (i = info_map.begin(); i != info_map.end(); ++i) { | 1595 for (i = info_map.begin(); i != info_map.end(); ++i) { |
1594 RenderViewHost* view = | 1596 RenderViewHost* view = |
1595 RenderViewHost::FromID(i->first.first, i->first.second); | 1597 RenderViewHost::FromID(i->first.first, i->first.second); |
1596 if (view) // The view could be gone at this point. | 1598 if (view) // The view could be gone at this point. |
1597 view->LoadStateChanged(i->second.url, i->second.load_state); | 1599 view->LoadStateChanged(i->second.url, i->second.load_state, |
| 1600 i->second.upload_position, |
| 1601 i->second.upload_size); |
1598 } | 1602 } |
1599 } | 1603 } |
1600 LoadInfoMap info_map; | 1604 LoadInfoMap info_map; |
1601 }; | 1605 }; |
1602 | 1606 |
1603 } // namespace | 1607 } // namespace |
1604 | 1608 |
1605 void ResourceDispatcherHost::UpdateLoadStates() { | 1609 void ResourceDispatcherHost::UpdateLoadStates() { |
1606 // Populate this map with load state changes, and then send them on to the UI | 1610 // Populate this map with load state changes, and then send them on to the UI |
1607 // thread where they can be passed along to the respective RVHs. | 1611 // thread where they can be passed along to the respective RVHs. |
1608 LoadInfoMap info_map; | 1612 LoadInfoMap info_map; |
1609 | 1613 |
1610 PendingRequestList::const_iterator i; | 1614 PendingRequestList::const_iterator i; |
| 1615 |
| 1616 // Determine the largest upload size of all requests |
| 1617 // in each View (good chance it's zero). |
| 1618 std::map<std::pair<int, int>, uint64> largest_upload_size; |
| 1619 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { |
| 1620 URLRequest* request = i->second; |
| 1621 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
| 1622 uint64 upload_size = info->upload_size(); |
| 1623 if (request->GetLoadState() != net::LOAD_STATE_SENDING_REQUEST) |
| 1624 upload_size = 0; |
| 1625 std::pair<int, int> key(info->child_id(), info->route_id()); |
| 1626 if (upload_size && largest_upload_size[key] < upload_size) |
| 1627 largest_upload_size[key] = upload_size; |
| 1628 } |
| 1629 |
1611 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { | 1630 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { |
1612 URLRequest* request = i->second; | 1631 URLRequest* request = i->second; |
1613 net::LoadState load_state = request->GetLoadState(); | 1632 net::LoadState load_state = request->GetLoadState(); |
1614 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); | 1633 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
1615 | 1634 |
1616 // We also poll for upload progress on this timer and send upload | 1635 // We also poll for upload progress on this timer and send upload |
1617 // progress ipc messages to the plugin process. | 1636 // progress ipc messages to the plugin process. |
1618 MaybeUpdateUploadProgress(info, request); | 1637 bool update_upload_progress = MaybeUpdateUploadProgress(info, request); |
1619 | 1638 |
1620 if (info->last_load_state() != load_state) { | 1639 if (info->last_load_state() != load_state || update_upload_progress) { |
| 1640 std::pair<int, int> key(info->child_id(), info->route_id()); |
| 1641 |
| 1642 // If a request is uploading data, ignore all other requests so that the |
| 1643 // upload progress takes priority for being shown in the status bar. |
| 1644 if (largest_upload_size.find(key) != largest_upload_size.end() && |
| 1645 info->upload_size() < largest_upload_size[key]) |
| 1646 continue; |
| 1647 |
1621 info->set_last_load_state(load_state); | 1648 info->set_last_load_state(load_state); |
1622 | 1649 |
1623 std::pair<int, int> key(info->child_id(), info->route_id()); | |
1624 net::LoadState to_insert; | 1650 net::LoadState to_insert; |
1625 LoadInfoMap::iterator existing = info_map.find(key); | 1651 LoadInfoMap::iterator existing = info_map.find(key); |
1626 if (existing == info_map.end()) { | 1652 if (existing == info_map.end()) { |
1627 to_insert = load_state; | 1653 to_insert = load_state; |
1628 } else { | 1654 } else { |
1629 to_insert = | 1655 to_insert = |
1630 MoreInterestingLoadState(existing->second.load_state, load_state); | 1656 MoreInterestingLoadState(existing->second.load_state, load_state); |
1631 if (to_insert == existing->second.load_state) | 1657 if (to_insert == existing->second.load_state) |
1632 continue; | 1658 continue; |
1633 } | 1659 } |
1634 LoadInfo& load_info = info_map[key]; | 1660 LoadInfo& load_info = info_map[key]; |
1635 load_info.url = request->url(); | 1661 load_info.url = request->url(); |
1636 load_info.load_state = to_insert; | 1662 load_info.load_state = to_insert; |
| 1663 load_info.upload_size = info->upload_size(); |
| 1664 load_info.upload_position = request->GetUploadProgress(); |
1637 } | 1665 } |
1638 } | 1666 } |
1639 | 1667 |
1640 if (info_map.empty()) | 1668 if (info_map.empty()) |
1641 return; | 1669 return; |
1642 | 1670 |
1643 LoadInfoUpdateTask* task = new LoadInfoUpdateTask; | 1671 LoadInfoUpdateTask* task = new LoadInfoUpdateTask; |
1644 task->info_map.swap(info_map); | 1672 task->info_map.swap(info_map); |
1645 ui_loop_->PostTask(FROM_HERE, task); | 1673 ui_loop_->PostTask(FROM_HERE, task); |
1646 } | 1674 } |
1647 | 1675 |
1648 void ResourceDispatcherHost::MaybeUpdateUploadProgress( | 1676 // Calls the ResourceHandler to send upload progress messages to the renderer. |
| 1677 // Returns true iff an upload progress message should be sent to the UI thread. |
| 1678 bool ResourceDispatcherHost::MaybeUpdateUploadProgress( |
1649 ResourceDispatcherHostRequestInfo *info, | 1679 ResourceDispatcherHostRequestInfo *info, |
1650 URLRequest *request) { | 1680 URLRequest *request) { |
1651 if (!info->upload_size() || info->waiting_for_upload_progress_ack() || | 1681 |
1652 !(request->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS)) | 1682 if (!info->upload_size() || info->waiting_for_upload_progress_ack()) |
1653 return; | 1683 return false; |
1654 | 1684 |
1655 uint64 size = info->upload_size(); | 1685 uint64 size = info->upload_size(); |
1656 uint64 position = request->GetUploadProgress(); | 1686 uint64 position = request->GetUploadProgress(); |
1657 if (position == info->last_upload_position()) | 1687 if (position == info->last_upload_position()) |
1658 return; // no progress made since last time | 1688 return false; // no progress made since last time |
1659 | 1689 |
1660 const uint64 kHalfPercentIncrements = 200; | 1690 const uint64 kHalfPercentIncrements = 200; |
1661 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); | 1691 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); |
1662 | 1692 |
1663 uint64 amt_since_last = position - info->last_upload_position(); | 1693 uint64 amt_since_last = position - info->last_upload_position(); |
1664 TimeDelta time_since_last = TimeTicks::Now() - info->last_upload_ticks(); | 1694 TimeDelta time_since_last = TimeTicks::Now() - info->last_upload_ticks(); |
1665 | 1695 |
1666 bool is_finished = (size == position); | 1696 bool is_finished = (size == position); |
1667 bool enough_new_progress = (amt_since_last > (size / kHalfPercentIncrements)); | 1697 bool enough_new_progress = (amt_since_last > (size / kHalfPercentIncrements)); |
1668 bool too_much_time_passed = time_since_last > kOneSecond; | 1698 bool too_much_time_passed = time_since_last > kOneSecond; |
1669 | 1699 |
1670 if (is_finished || enough_new_progress || too_much_time_passed) { | 1700 if (is_finished || enough_new_progress || too_much_time_passed) { |
1671 info->resource_handler()->OnUploadProgress(info->request_id(), | 1701 if (request->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) { |
1672 position, size); | 1702 info->resource_handler()->OnUploadProgress(info->request_id(), |
1673 info->set_waiting_for_upload_progress_ack(true); | 1703 position, size); |
| 1704 info->set_waiting_for_upload_progress_ack(true); |
| 1705 } |
1674 info->set_last_upload_ticks(TimeTicks::Now()); | 1706 info->set_last_upload_ticks(TimeTicks::Now()); |
1675 info->set_last_upload_position(position); | 1707 info->set_last_upload_position(position); |
| 1708 return true; |
1676 } | 1709 } |
| 1710 return false; |
1677 } | 1711 } |
1678 | 1712 |
1679 void ResourceDispatcherHost::BlockRequestsForRoute(int child_id, int route_id) { | 1713 void ResourceDispatcherHost::BlockRequestsForRoute(int child_id, int route_id) { |
1680 std::pair<int, int> key(child_id, route_id); | 1714 std::pair<int, int> key(child_id, route_id); |
1681 DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << | 1715 DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << |
1682 "BlockRequestsForRoute called multiple time for the same RVH"; | 1716 "BlockRequestsForRoute called multiple time for the same RVH"; |
1683 blocked_requests_map_[key] = new BlockedRequestsList(); | 1717 blocked_requests_map_[key] = new BlockedRequestsList(); |
1684 } | 1718 } |
1685 | 1719 |
1686 void ResourceDispatcherHost::ResumeBlockedRequestsForRoute(int child_id, | 1720 void ResourceDispatcherHost::ResumeBlockedRequestsForRoute(int child_id, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 case ViewHostMsg_UploadProgress_ACK::ID: | 1773 case ViewHostMsg_UploadProgress_ACK::ID: |
1740 case ViewHostMsg_SyncLoad::ID: | 1774 case ViewHostMsg_SyncLoad::ID: |
1741 return true; | 1775 return true; |
1742 | 1776 |
1743 default: | 1777 default: |
1744 break; | 1778 break; |
1745 } | 1779 } |
1746 | 1780 |
1747 return false; | 1781 return false; |
1748 } | 1782 } |
OLD | NEW |