| 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 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1823 // in the order in which they occur during the lifetime of a request, so we can | 1823 // in the order in which they occur during the lifetime of a request, so we can |
| 1824 // regard states with larger numeric values as being further along toward | 1824 // regard states with larger numeric values as being further along toward |
| 1825 // completion. We regard those states as more interesting to report since they | 1825 // completion. We regard those states as more interesting to report since they |
| 1826 // represent progress. | 1826 // represent progress. |
| 1827 // | 1827 // |
| 1828 // For example, by this measure "tranferring data" is a more interesting state | 1828 // For example, by this measure "tranferring data" is a more interesting state |
| 1829 // than "resolving host" because when we are transferring data we are actually | 1829 // than "resolving host" because when we are transferring data we are actually |
| 1830 // doing something that corresponds to changes that the user might observe, | 1830 // doing something that corresponds to changes that the user might observe, |
| 1831 // whereas waiting for a host name to resolve implies being stuck. | 1831 // whereas waiting for a host name to resolve implies being stuck. |
| 1832 // | 1832 // |
| 1833 net::LoadState MoreInterestingLoadState(net::LoadState a, net::LoadState b) { | 1833 const net::LoadStateWithParam& MoreInterestingLoadState( |
| 1834 return (a < b) ? b : a; | 1834 const net::LoadStateWithParam& a, const net::LoadStateWithParam& b) { |
| 1835 return (a.state < b.state) ? b : a; |
| 1835 } | 1836 } |
| 1836 | 1837 |
| 1837 // Carries information about a load state change. | 1838 // Carries information about a load state change. |
| 1838 struct LoadInfo { | 1839 struct LoadInfo { |
| 1839 GURL url; | 1840 GURL url; |
| 1840 net::LoadState load_state; | 1841 net::LoadStateWithParam load_state; |
| 1841 uint64 upload_position; | 1842 uint64 upload_position; |
| 1842 uint64 upload_size; | 1843 uint64 upload_size; |
| 1843 }; | 1844 }; |
| 1844 | 1845 |
| 1845 // Map from ProcessID+ViewID pair to LoadState | 1846 // Map from ProcessID+ViewID pair to LoadState |
| 1846 typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap; | 1847 typedef std::map<std::pair<int, int>, LoadInfo> LoadInfoMap; |
| 1847 | 1848 |
| 1848 // Used to marshall calls to LoadStateChanged from the IO to UI threads. We do | 1849 // Used to marshall calls to LoadStateChanged from the IO to UI threads. We do |
| 1849 // them all as a single task to avoid spamming the UI thread. | 1850 // them all as a single task to avoid spamming the UI thread. |
| 1850 class LoadInfoUpdateTask : public Task { | 1851 class LoadInfoUpdateTask : public Task { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1872 | 1873 |
| 1873 PendingRequestList::const_iterator i; | 1874 PendingRequestList::const_iterator i; |
| 1874 | 1875 |
| 1875 // Determine the largest upload size of all requests | 1876 // Determine the largest upload size of all requests |
| 1876 // in each View (good chance it's zero). | 1877 // in each View (good chance it's zero). |
| 1877 std::map<std::pair<int, int>, uint64> largest_upload_size; | 1878 std::map<std::pair<int, int>, uint64> largest_upload_size; |
| 1878 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { | 1879 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { |
| 1879 net::URLRequest* request = i->second; | 1880 net::URLRequest* request = i->second; |
| 1880 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); | 1881 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
| 1881 uint64 upload_size = info->upload_size(); | 1882 uint64 upload_size = info->upload_size(); |
| 1882 if (request->GetLoadState() != net::LOAD_STATE_SENDING_REQUEST) | 1883 if (request->GetLoadState().state != net::LOAD_STATE_SENDING_REQUEST) |
| 1883 upload_size = 0; | 1884 upload_size = 0; |
| 1884 std::pair<int, int> key(info->child_id(), info->route_id()); | 1885 std::pair<int, int> key(info->child_id(), info->route_id()); |
| 1885 if (upload_size && largest_upload_size[key] < upload_size) | 1886 if (upload_size && largest_upload_size[key] < upload_size) |
| 1886 largest_upload_size[key] = upload_size; | 1887 largest_upload_size[key] = upload_size; |
| 1887 } | 1888 } |
| 1888 | 1889 |
| 1889 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { | 1890 for (i = pending_requests_.begin(); i != pending_requests_.end(); ++i) { |
| 1890 net::URLRequest* request = i->second; | 1891 net::URLRequest* request = i->second; |
| 1891 net::LoadState load_state = request->GetLoadState(); | 1892 net::LoadStateWithParam load_state = request->GetLoadState(); |
| 1892 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); | 1893 ResourceDispatcherHostRequestInfo* info = InfoForRequest(request); |
| 1894 std::pair<int, int> key(info->child_id(), info->route_id()); |
| 1893 | 1895 |
| 1894 // We also poll for upload progress on this timer and send upload | 1896 // We also poll for upload progress on this timer and send upload |
| 1895 // progress ipc messages to the plugin process. | 1897 // progress ipc messages to the plugin process. |
| 1896 bool update_upload_progress = MaybeUpdateUploadProgress(info, request); | 1898 MaybeUpdateUploadProgress(info, request); |
| 1897 | 1899 |
| 1898 if (info->last_load_state() != load_state || update_upload_progress) { | 1900 // If a request is uploading data, ignore all other requests so that the |
| 1899 std::pair<int, int> key(info->child_id(), info->route_id()); | 1901 // upload progress takes priority for being shown in the status bar. |
| 1902 if (largest_upload_size.find(key) != largest_upload_size.end() && |
| 1903 info->upload_size() < largest_upload_size[key]) |
| 1904 continue; |
| 1900 | 1905 |
| 1901 // If a request is uploading data, ignore all other requests so that the | 1906 net::LoadStateWithParam to_insert = load_state; |
| 1902 // upload progress takes priority for being shown in the status bar. | 1907 LoadInfoMap::iterator existing = info_map.find(key); |
| 1903 if (largest_upload_size.find(key) != largest_upload_size.end() && | 1908 if (existing != info_map.end()) { |
| 1904 info->upload_size() < largest_upload_size[key]) | 1909 to_insert = |
| 1910 MoreInterestingLoadState(existing->second.load_state, load_state); |
| 1911 if (to_insert.state == existing->second.load_state.state) |
| 1905 continue; | 1912 continue; |
| 1906 | |
| 1907 info->set_last_load_state(load_state); | |
| 1908 | |
| 1909 net::LoadState to_insert; | |
| 1910 LoadInfoMap::iterator existing = info_map.find(key); | |
| 1911 if (existing == info_map.end()) { | |
| 1912 to_insert = load_state; | |
| 1913 } else { | |
| 1914 to_insert = | |
| 1915 MoreInterestingLoadState(existing->second.load_state, load_state); | |
| 1916 if (to_insert == existing->second.load_state) | |
| 1917 continue; | |
| 1918 } | |
| 1919 LoadInfo& load_info = info_map[key]; | |
| 1920 load_info.url = request->url(); | |
| 1921 load_info.load_state = to_insert; | |
| 1922 load_info.upload_size = info->upload_size(); | |
| 1923 load_info.upload_position = request->GetUploadProgress(); | |
| 1924 } | 1913 } |
| 1914 LoadInfo& load_info = info_map[key]; |
| 1915 load_info.url = request->url(); |
| 1916 load_info.load_state = to_insert; |
| 1917 load_info.upload_size = info->upload_size(); |
| 1918 load_info.upload_position = request->GetUploadProgress(); |
| 1925 } | 1919 } |
| 1926 | 1920 |
| 1927 if (info_map.empty()) | 1921 if (info_map.empty()) |
| 1928 return; | 1922 return; |
| 1929 | 1923 |
| 1930 LoadInfoUpdateTask* task = new LoadInfoUpdateTask; | 1924 LoadInfoUpdateTask* task = new LoadInfoUpdateTask; |
| 1931 task->info_map.swap(info_map); | 1925 task->info_map.swap(info_map); |
| 1932 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task); | 1926 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task); |
| 1933 } | 1927 } |
| 1934 | 1928 |
| 1935 // Calls the ResourceHandler to send upload progress messages to the renderer. | 1929 // Calls the ResourceHandler to send upload progress messages to the renderer. |
| 1936 // Returns true iff an upload progress message should be sent to the UI thread. | 1930 void ResourceDispatcherHost::MaybeUpdateUploadProgress( |
| 1937 bool ResourceDispatcherHost::MaybeUpdateUploadProgress( | |
| 1938 ResourceDispatcherHostRequestInfo *info, | 1931 ResourceDispatcherHostRequestInfo *info, |
| 1939 net::URLRequest *request) { | 1932 net::URLRequest *request) { |
| 1940 | 1933 |
| 1941 if (!info->upload_size() || info->waiting_for_upload_progress_ack()) | 1934 if (!info->upload_size() || info->waiting_for_upload_progress_ack()) |
| 1942 return false; | 1935 return; |
| 1943 | 1936 |
| 1944 uint64 size = info->upload_size(); | 1937 uint64 size = info->upload_size(); |
| 1945 uint64 position = request->GetUploadProgress(); | 1938 uint64 position = request->GetUploadProgress(); |
| 1946 if (position == info->last_upload_position()) | 1939 if (position == info->last_upload_position()) |
| 1947 return false; // no progress made since last time | 1940 return; // no progress made since last time |
| 1948 | 1941 |
| 1949 const uint64 kHalfPercentIncrements = 200; | 1942 const uint64 kHalfPercentIncrements = 200; |
| 1950 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); | 1943 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); |
| 1951 | 1944 |
| 1952 uint64 amt_since_last = position - info->last_upload_position(); | 1945 uint64 amt_since_last = position - info->last_upload_position(); |
| 1953 TimeDelta time_since_last = TimeTicks::Now() - info->last_upload_ticks(); | 1946 TimeDelta time_since_last = TimeTicks::Now() - info->last_upload_ticks(); |
| 1954 | 1947 |
| 1955 bool is_finished = (size == position); | 1948 bool is_finished = (size == position); |
| 1956 bool enough_new_progress = (amt_since_last > (size / kHalfPercentIncrements)); | 1949 bool enough_new_progress = (amt_since_last > (size / kHalfPercentIncrements)); |
| 1957 bool too_much_time_passed = time_since_last > kOneSecond; | 1950 bool too_much_time_passed = time_since_last > kOneSecond; |
| 1958 | 1951 |
| 1959 if (is_finished || enough_new_progress || too_much_time_passed) { | 1952 if (is_finished || enough_new_progress || too_much_time_passed) { |
| 1960 if (request->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) { | 1953 if (request->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) { |
| 1961 info->resource_handler()->OnUploadProgress(info->request_id(), | 1954 info->resource_handler()->OnUploadProgress(info->request_id(), |
| 1962 position, size); | 1955 position, size); |
| 1963 info->set_waiting_for_upload_progress_ack(true); | 1956 info->set_waiting_for_upload_progress_ack(true); |
| 1964 } | 1957 } |
| 1965 info->set_last_upload_ticks(TimeTicks::Now()); | 1958 info->set_last_upload_ticks(TimeTicks::Now()); |
| 1966 info->set_last_upload_position(position); | 1959 info->set_last_upload_position(position); |
| 1967 return true; | |
| 1968 } | 1960 } |
| 1969 return false; | |
| 1970 } | 1961 } |
| 1971 | 1962 |
| 1972 void ResourceDispatcherHost::BlockRequestsForRoute(int child_id, int route_id) { | 1963 void ResourceDispatcherHost::BlockRequestsForRoute(int child_id, int route_id) { |
| 1973 std::pair<int, int> key(child_id, route_id); | 1964 std::pair<int, int> key(child_id, route_id); |
| 1974 DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << | 1965 DCHECK(blocked_requests_map_.find(key) == blocked_requests_map_.end()) << |
| 1975 "BlockRequestsForRoute called multiple time for the same RVH"; | 1966 "BlockRequestsForRoute called multiple time for the same RVH"; |
| 1976 blocked_requests_map_[key] = new BlockedRequestsList(); | 1967 blocked_requests_map_[key] = new BlockedRequestsList(); |
| 1977 } | 1968 } |
| 1978 | 1969 |
| 1979 void ResourceDispatcherHost::ResumeBlockedRequestsForRoute(int child_id, | 1970 void ResourceDispatcherHost::ResumeBlockedRequestsForRoute(int child_id, |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2125 return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; | 2116 return HTTP_AUTH_RESOURCE_BLOCKED_CROSS; |
| 2126 } | 2117 } |
| 2127 | 2118 |
| 2128 bool ResourceDispatcherHost::allow_cross_origin_auth_prompt() { | 2119 bool ResourceDispatcherHost::allow_cross_origin_auth_prompt() { |
| 2129 return allow_cross_origin_auth_prompt_; | 2120 return allow_cross_origin_auth_prompt_; |
| 2130 } | 2121 } |
| 2131 | 2122 |
| 2132 void ResourceDispatcherHost::set_allow_cross_origin_auth_prompt(bool value) { | 2123 void ResourceDispatcherHost::set_allow_cross_origin_auth_prompt(bool value) { |
| 2133 allow_cross_origin_auth_prompt_ = value; | 2124 allow_cross_origin_auth_prompt_ = value; |
| 2134 } | 2125 } |
| OLD | NEW |