001package Torello.Browser; 002 003import static Torello.Java.C.BRED; 004import static Torello.Java.C.BCYAN; 005import static Torello.Java.C.RESET; 006 007import Torello.Browser.BrowserAPI.Network; 008import Torello.Browser.BrowserAPI.Page; 009import Torello.Browser.BrowserAPI.Target; 010 011import Torello.Java.StrIndent; 012 013import java.util.ArrayList; 014import java.util.Base64; 015import java.util.List; 016 017import java.nio.file.Files; 018import java.nio.file.Paths; 019 020/** 021 * Demonstrates several CDP browser features without using JavaScript evaluation. 022 * <EMBED CLASS='external-html' DATA-FILE-ID=EX03_EXAMPLE> 023 */ 024public class Example03 025{ 026 private Example03() { } 027 028 /** The URL used for demonstrating Network, Page, Screenshot, PDF and Cookie commands. */ 029 protected static final String chineseURL = 030 "https://zh.wikipedia.org/wiki/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD"; 031 032 /** The files generated by this example. */ 033 protected static final String screenshotFile = "Example03-Screenshot.png"; 034 protected static final String pdfFile = "Example03-Page.pdf"; 035 036 private static ConnRecord connRec = new ConnRecord(); 037 038 static 039 { 040 connRec.setEventHandler(Example03::eventHandler); 041 connRec.setRawTextReceiver(System.out); 042 connRec.setErrTextReceiver(System.out); 043 } 044 045 046 047 // ******************************************************************************************** 048 // ******************************************************************************************** 049 // Printing Helpers 050 // ******************************************************************************************** 051 // ******************************************************************************************** 052 053 054 /** Network URLs collected by the page-level handler. */ 055 protected static final List<String> networkURLs = new ArrayList<>(); 056 057 /** Page-level handler; this is where Network events become useful. */ 058 static void eventHandler(BrowserEvent<?> be) 059 { 060 if (be instanceof Network.requestWillBeSent) 061 { 062 final Network.requestWillBeSent r = (Network.requestWillBeSent) be; 063 064 networkURLs.add(r.request.url); 065 066 System.out.println( 067 '\n' + BCYAN + "Example03.java: " + RESET + 068 BRED + "Network.requestWillBeSent" + RESET + '\n' + 069 " " + r.request.method + " " + r.request.url 070 ); 071 } 072 073 else if (be instanceof Network.responseReceived) 074 { 075 final Network.responseReceived r = (Network.responseReceived) be; 076 077 System.out.println( 078 '\n' + BCYAN + "Example03.java: " + RESET + 079 BRED + "Network.responseReceived" + RESET + '\n' + 080 " " + r.response.status + " " + r.response.mimeType + '\n' + 081 " " + r.response.url 082 ); 083 } 084 085 else if (be instanceof Network.loadingFinished) 086 { 087 final Network.loadingFinished r = (Network.loadingFinished) be; 088 089 System.out.println( 090 '\n' + BCYAN + "Example03.java: " + RESET + 091 BRED + "Network.loadingFinished" + RESET + '\n' + 092 " requestId: " + r.requestId + '\n' + 093 " bytes: " + r.encodedDataLength 094 ); 095 } 096 }; 097 098 099 // ******************************************************************************************** 100 // ******************************************************************************************** 101 // MAIN METHOD 102 // ******************************************************************************************** 103 // ******************************************************************************************** 104 105 106 /** This class is intended to be invoked from the Command Line. */ 107 public static void main(String[] argv) throws Exception 108 { 109 STEP_01_initializeBrowserAndPage(); 110 111 try 112 { 113 STEP_02_enablePageAndNetwork(connRec.pws); 114 115 STEP_03_navigateAndCollectNetworkTraffic(connRec.pws); 116 117 STEP_04_captureScreenshot(connRec.pws); 118 119 STEP_05_printToPDF(connRec.pws); 120 121 STEP_06_printCookies(connRec.pws); 122 } 123 124 finally 125 { 126 connRec.bws.disconnect(); 127 connRec.pws.disconnect(); 128 } 129 } 130 131 132 // ******************************************************************************************** 133 // ******************************************************************************************** 134 // The Steps 135 // ******************************************************************************************** 136 // ******************************************************************************************** 137 138 139 /** Open Chrome, close old tabs, create a new tab, and return both WebSocket senders. */ 140 protected static void STEP_01_initializeBrowserAndPage() throws Exception 141 { 142 Printing.notice("Initialize BrowserConn, PageConn and WebSocketSender"); 143 144 final BrowserConn browserConn = BrowserConn.getBrowserConn(9222, false); 145 146 System.out.println( 147 '\n' + BCYAN + "Example03.java: " + RESET + 148 BRED + "Opened Browser Connection:\n" + RESET + browserConn.toString() 149 ); 150 151 final WebSocketSender bws = browserConn.createSender(connRec); 152 153 final Target.TargetInfo[] allTabs = Target 154 .getTargets(null /* FilterEntry[] */) 155 .exec(bws) 156 .await(); 157 158 for (int i = 0; i < allTabs.length; i++) 159 if ("page".equals(allTabs[i].type)) 160 Target.closeTarget(allTabs[i].targetId).exec(bws).await(); 161 162 final String targetID = Target 163 .createTarget() 164 .accept("url", "about:blank") 165 .build() 166 .exec(bws) 167 .await(); 168 169 final PageConn pageConn = PageConn 170 .getAllPageConn(9222, false) 171 .filter((PageConn pc) -> pc.id.equals(targetID)) 172 .findFirst() 173 .orElseThrow(() -> new RuntimeException("The Page-Connection was Not Found")); 174 175 System.out.println( 176 '\n' + BCYAN + "Example03.java: " + RESET + 177 BRED + "Opened Page Connection:\n" + RESET + pageConn.toString() 178 ); 179 180 final WebSocketSender pws = pageConn.createSender(connRec); 181 182 Thread.sleep(1000); 183 184 connRec.bws = bws; 185 connRec.pws = pws; 186 } 187 188 /** Enables the two CDP domains used throughout this example. */ 189 protected static void STEP_02_enablePageAndNetwork(final WebSocketSender pws) throws Exception 190 { 191 Printing.notice("Enable Page and Network Domains"); 192 193 System.out.println('\n' + BCYAN + "Example03.java: " + RESET + "Page.enable()"); 194 Page.enable(null /* enableFileChooserOpenedEvent */).exec(connRec.pws).await(); 195 196 System.out.println('\n' + BCYAN + "Example03.java: " + RESET + "Network.enable()"); 197 Network 198 .enable( 199 null, // maxTotalBufferSize 200 null, // maxResourceBufferSize 201 null, // maxPostDataSize, 202 null // reportDirectSocketTraffic 203 ) 204 .exec(connRec.pws) 205 .await(); 206 } 207 208 /** Navigate to the target page and allow Network events to arrive through the handler. */ 209 protected static void STEP_03_navigateAndCollectNetworkTraffic(final WebSocketSender pws) 210 throws Exception 211 { 212 Printing.notice("Navigate and Collect Network Traffic"); 213 214 System.out.println( 215 '\n' + BCYAN + "Example03.java: " + RESET + 216 "Navigating To: " + chineseURL 217 ); 218 219 Page 220 .navigate() 221 .accept("url", chineseURL) 222 .build() 223 .exec(connRec.pws) 224 .await(); 225 226 Thread.sleep(5000); 227 228 System.out.println( 229 '\n' + BCYAN + "Example03.java: " + RESET + 230 BRED + "Total Network Request URL's Collected: " + RESET + 231 networkURLs.size() 232 ); 233 234 for (int i = 0; i < networkURLs.size(); i++) 235 System.out.println(" " + networkURLs.get(i)); 236 } 237 238 /** Capture the rendered browser page as a PNG file. */ 239 protected static void STEP_04_captureScreenshot(final WebSocketSender pws) throws Exception 240 { 241 Printing.notice("Capture a PNG Screenshot"); 242 243 final String pngBase64 = Page 244 .captureScreenshot() 245 .accept("format", "png") 246 .accept("fromSurface", true) 247 .build() 248 .exec(connRec.pws) 249 .await(); 250 251 Files.write(Paths.get(screenshotFile), Base64.getDecoder().decode(pngBase64)); 252 253 System.out.println( 254 '\n' + BCYAN + "Example03.java: " + RESET + 255 BRED + "Wrote Screenshot File: " + RESET + screenshotFile 256 ); 257 } 258 259 /** Print the rendered browser page to a PDF file. */ 260 protected static void STEP_05_printToPDF(final WebSocketSender pws) throws Exception 261 { 262 Printing.notice("Print the Page to a PDF File"); 263 264 final Page.printToPDF$$RET pdf = Page 265 .printToPDF() 266 .accept("printBackground", true) 267 .build() 268 .exec(connRec.pws) 269 .await(); 270 271 Files.write(Paths.get(pdfFile), Base64.getDecoder().decode(pdf.data)); 272 273 System.out.println( 274 '\n' + BCYAN + "Example03.java: " + RESET + 275 BRED + "Wrote PDF File: " + RESET + pdfFile 276 ); 277 } 278 279 /** Print the cookies visible to Chrome for the current page. */ 280 protected static void STEP_06_printCookies(final WebSocketSender pws) throws Exception 281 { 282 Printing.notice("Read Browser Cookies for the Current Page"); 283 284 final Network.Cookie[] cookies = Network 285 .getCookies(null /* String[] urls */) 286 .exec(connRec.pws) 287 .await(); 288 289 System.out.println( 290 '\n' + BCYAN + "Example03.java: " + RESET + 291 BRED + "Cookies Returned: " + RESET + cookies.length 292 ); 293 294 for (int i = 0; i < cookies.length; i++) 295 System.out.println(StrIndent.indent(cookies[i].toString(), 4)); 296 } 297}