OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/renderer_host/resource_dispatcher_host.h" | 7 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
8 | 8 |
9 #include <set> | 9 #include <set> |
10 #include <vector> | 10 #include <vector> |
(...skipping 1773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1784 // in the order in which they occur during the lifetime of a request, so we can | 1784 // in the order in which they occur during the lifetime of a request, so we can |
1785 // regard states with larger numeric values as being further along toward | 1785 // regard states with larger numeric values as being further along toward |
1786 // completion. We regard those states as more interesting to report since they | 1786 // completion. We regard those states as more interesting to report since they |
1787 // represent progress. | 1787 // represent progress. |
1788 // | 1788 // |
1789 // For example, by this measure "tranferring data" is a more interesting state | 1789 // For example, by this measure "tranferring data" is a more interesting state |
1790 // than "resolving host" because when we are transferring data we are actually | 1790 // than "resolving host" because when we are transferring data we are actually |
1791 // doing something that corresponds to changes that the user might observe, | 1791 // doing something that corresponds to changes that the user might observe, |
1792 // whereas waiting for a host name to resolve implies being stuck. | 1792 // whereas waiting for a host name to resolve implies being stuck. |
1793 // | 1793 // |
1794 net::LoadState MoreInterestingLoadState(net::LoadState a, net::LoadState b) { | 1794 const net::LoadStateWithParam& MoreInterestingLoadState( |
1795 return (a < b) ? b : a; | 1795 const net::LoadStateWithParam& a, const net::LoadStateWithParam& b) { |
1796 return (a.state < b.state) ? b : a; | |
1796 } | 1797 } |
1797 | 1798 |
1798 // Carries information about a load state change. | 1799 // Carries information about a load state change. |
1799 struct LoadInfo { | 1800 struct LoadInfo { |
1800 GURL url; | 1801 GURL url; |
1801 net::LoadState load_state; | 1802 net::LoadStateWithParam load_state; |
1802 uint64 upload_position; | 1803 uint64 upload_position; |
1803 uint64 upload_size; | 1804 uint64 upload_size; |
1804 }; | 1805 }; |
1805 | 1806 |
1806 // Map from ProcessID+ViewID pair to LoadState | 1807 // Map from ProcessID+ViewID pair to LoadState |
1807 typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap; | 1808 typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap; |
1808 | 1809 |
1809 // Used to marshall calls to LoadStateChanged from the IO to UI threads. We do | 1810 // Used to marshall calls to LoadStateChanged from the IO to UI threads. We do |
1810 // them all as a single task to avoid spamming the UI thread. | 1811 // them all as a single task to avoid spamming the UI thread. |
1811 class LoadInfoUpdateTask : public Task { | 1812 class LoadInfoUpdateTask : public Task { |
(...skipping 21 matching lines...) Expand all Loading... | |
1833 | 1834 |
1834 PendingRequestList::const_iterator i; | 1835 PendingRequestList::const_iterator i; |
1835 | 1836 |
1836 // Determine the largest upload size of all requests | 1837 // Determine the largest upload size of all requests |
1837 // in each View (good chance it's zero). | 1838 // in each View (good chance it's zero). |
1838 std::map<std::pair<int, int>, uint64> largest_upload_size; | 1839 std::map<std::pair<int, int>, uint64> largest_upload_size; |
1839 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { | 1840 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { |
1840 net::URLRequest* request = i->second; | 1841 net::URLRequest* request = i->second; |
1841 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); | 1842 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
1842 uint64 upload_size = info->upload_size(); | 1843 uint64 upload_size = info->upload_size(); |
1843 if (request->GetLoadState() != net::LOAD_STATE_SENDING_REQUEST) | 1844 if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST) |
1844 upload_size = 0; | 1845 upload_size = 0; |
1845 std::pair<int, int> key(info->child_id(), info->route_id()); | 1846 std::pair<int, int> key(info->child_id(), info->route_id()); |
1846 if (upload_size && largest_upload_size[key] < upload_size) | 1847 if (upload_size && largest_upload_size[key] < upload_size) |
1847 largest_upload_size[key] = upload_size; | 1848 largest_upload_size[key] = upload_size; |
1848 } | 1849 } |
1849 | 1850 |
1850 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { | 1851 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { |
1851 net::URLRequest* request = i->second; | 1852 net::URLRequest* request = i->second; |
1852 net::LoadState load_state = request->GetLoadState(); | 1853 net::LoadStateWithParam load_state = request->GetLoadState(); |
1853 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); | 1854 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
1855 std::pair<int, int> key(info->child_id(), info->route_id()); | |
1854 | 1856 |
1855 // We also poll for upload progress on this timer and send upload | 1857 // We also poll for upload progress on this timer and send upload |
1856 // progress ipc messages to the plugin process. | 1858 // progress ipc messages to the plugin process. |
1857 bool update_upload_progress = MaybeUpdateUploadProgress(info, request); | 1859 MaybeUpdateUploadProgress(info, request); |
1858 | 1860 |
1859 if (info->last_load_state() != load_state || update_upload_progress) { | 1861 // If a request is uploading data, ignore all other requests so that the |
Matt Perry
2011/07/29 00:36:54
I believe this logic was wrong. Consider this scen
| |
1860 std::pair<int, int> key(info->child_id(), info->route_id()); | 1862 // upload progress takes priority for being shown in the status bar. |
1863 if (largest_upload_size.find(key) != largest_upload_size.end() && | |
1864 info->upload_size() < largest_upload_size[key]) | |
1865 continue; | |
1861 | 1866 |
1862 // If a request is uploading data, ignore all other requests so that the | 1867 net::LoadStateWithParam to_insert = load_state; |
1863 // upload progress takes priority for being shown in the status bar. | 1868 LoadInfoMap::iterator existing = info_map.find(key); |
1864 if (largest_upload_size.find(key) != largest_upload_size.end() && | 1869 if (existing != info_map.end()) { |
1865 info->upload_size() < largest_upload_size[key]) | 1870 to_insert = |
1871 MoreInterestingLoadState(existing->second.load_state, load_state); | |
1872 if (to_insert.state == existing->second.load_state.state) | |
1866 continue; | 1873 continue; |
1867 | |
1868 info->set_last_load_state(load_state); | |
1869 | |
1870 net::LoadState to_insert; | |
1871 LoadInfoMap::iterator existing = info_map.find(key); | |
1872 if (existing == info_map.end()) { | |
1873 to_insert = load_state; | |
1874 } else { | |
1875 to_insert = | |
1876 MoreInterestingLoadState(existing->second.load_state, load_state); | |
1877 if (to_insert == existing->second.load_state) | |
1878 continue; | |
1879 } | |
1880 LoadInfo& load_info = info_map[key]; | |
1881 load_info.url = request->url(); | |
1882 load_info.load_state = to_insert; | |
1883 load_info.upload_size = info->upload_size(); | |
1884 load_info.upload_position = request->GetUploadProgress(); | |
1885 } | 1874 } |
1875 LoadInfo& load_info = info_map[key]; | |
1876 load_info.url = request->url(); | |
1877 load_info.load_state = to_insert; | |
1878 load_info.upload_size = info->upload_size(); | |
1879 load_info.upload_position = request->GetUploadProgress(); | |
1886 } | 1880 } |
1887 | 1881 |
1888 if (info_map.empty()) | 1882 if (info_map.empty()) |
1889 return; | 1883 return; |
1890 | 1884 |
1891 LoadInfoUpdateTask* task = new LoadInfoUpdateTask; | 1885 LoadInfoUpdateTask* task = new LoadInfoUpdateTask; |
1892 task->info_map.swap(info_map); | 1886 task->info_map.swap(info_map); |
1893 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task); | 1887 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task); |
1894 } | 1888 } |
1895 | 1889 |
1896 // Calls the ResourceHandler to send upload progress messages to the renderer. | 1890 // Calls the ResourceHandler to send upload progress messages to the renderer. |
1897 // Returns true iff an upload progress message should be sent to the UI thread. | 1891 void ResourceDispatcherHost::MaybeUpdateUploadProgress( |
1898 bool ResourceDispatcherHost::MaybeUpdateUploadProgress( | |
1899 ResourceDispatcherHostRequestInfo *info, | 1892 ResourceDispatcherHostRequestInfo *info, |
1900 net::URLRequest *request) { | 1893 net::URLRequest *request) { |
1901 | 1894 |
1902 if (!info->upload_size() || info->waiting_for_upload_progress_ack()) | 1895 if (!info->upload_size() || info->waiting_for_upload_progress_ack()) |
1903 return false; | 1896 return; |
1904 | 1897 |
1905 uint64 size = info->upload_size(); | 1898 uint64 size = info->upload_size(); |
1906 uint64 position = request->GetUploadProgress(); | 1899 uint64 position = request->GetUploadProgress(); |
1907 if (position == info->last_upload_position()) | 1900 if (position == info->last_upload_position()) |
1908 return false; // no progress made since last time | 1901 return; // no progress made since last time |
1909 | 1902 |
1910 const uint64 kHalfPercentIncrements = 200; | 1903 const uint64 kHalfPercentIncrements = 200; |
1911 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); | 1904 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); |
1912 | 1905 |
1913 uint64 amt_since_last = position - info->last_upload_position(); | 1906 uint64 amt_since_last = position - info->last_upload_position(); |
1914 TimeDelta time_since_last = TimeTicks::Now() - info->last_upload_ticks(); | 1907 TimeDelta time_since_last = TimeTicks::Now() - info->last_upload_ticks(); |
1915 | 1908 |
1916 bool is_finished = (size == position); | 1909 bool is_finished = (size == position); |
1917 bool enough_new_progress = (amt_since_last > (size / kHalfPercentIncrements)); | 1910 bool enough_new_progress = (amt_since_last > (size / kHalfPercentIncrements)); |
1918 bool too_much_time_passed = time_since_last > kOneSecond; | 1911 bool too_much_time_passed = time_since_last > kOneSecond; |
1919 | 1912 |
1920 if (is_finished || enough_new_progress || too_much_time_passed) { | 1913 if (is_finished || enough_new_progress || too_much_time_passed) { |
1921 if (request->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) { | 1914 if (request->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) { |
1922 info->resource_handler()->OnUploadProgress(info->request_id(), | 1915 info->resource_handler()->OnUploadProgress(info->request_id(), |
1923 position, size); | 1916 position, size); |
1924 info->set_waiting_for_upload_progress_ack(true); | 1917 info->set_waiting_for_upload_progress_ack(true); |
1925 } | 1918 } |
1926 info->set_last_upload_ticks(TimeTicks::Now()); | 1919 info->set_last_upload_ticks(TimeTicks::Now()); |
1927 info->set_last_upload_position(position); | 1920 info->set_last_upload_position(position); |
1928 return true; | |
1929 } | 1921 } |
1930 return false; | |
1931 } | 1922 } |
1932 | 1923 |
1933 void ResourceDispatcherHost::BlockRequestsForRoute(int child_id, int route_id) { | 1924 void ResourceDispatcherHost::BlockRequestsForRoute(int child_id, int route_id) { |
1934 std::pair<int, int> key(child_id, route_id); | 1925 std::pair<int, int> key(child_id, route_id); |
1935 DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << | 1926 DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << |
1936 "BlockRequestsForRoute called multiple time for the same RVH"; | 1927 "BlockRequestsForRoute called multiple time for the same RVH"; |
1937 blocked_requests_map_[key] = new BlockedRequestsList(); | 1928 blocked_requests_map_[key] = new BlockedRequestsList(); |
1938 } | 1929 } |
1939 | 1930 |
1940 void ResourceDispatcherHost::ResumeBlockedRequestsForRoute(int child_id, | 1931 void ResourceDispatcherHost::ResumeBlockedRequestsForRoute(int child_id, |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2085 return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; | 2076 return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; |
2086 } | 2077 } |
2087 | 2078 |
2088 bool ResourceDispatcherHost::allow_cross_origin_auth_prompt() { | 2079 bool ResourceDispatcherHost::allow_cross_origin_auth_prompt() { |
2089 return allow_cross_origin_auth_prompt_; | 2080 return allow_cross_origin_auth_prompt_; |
2090 } | 2081 } |
2091 | 2082 |
2092 void ResourceDispatcherHost::set_allow_cross_origin_auth_prompt(bool value) { | 2083 void ResourceDispatcherHost::set_allow_cross_origin_auth_prompt(bool value) { |
2093 allow_cross_origin_auth_prompt_ = value; | 2084 allow_cross_origin_auth_prompt_ = value; |
2094 } | 2085 } |
OLD | NEW |